1、自动终断【完成】:一个线程完成执行后(即run方法执行完毕),不能再次运行 。
2、手动中断:
stop( ) —— 已过时,基本不用。(不安全,就像是突然停电)
interrupt( ) ——此方法只是改变中断状态,不会中断一个正在运行的线程。比如:如果当前线程是阻塞状态,那么就结束阻塞状态
3、可通过使用一个标志指示 run 方法退出,从而终止线程(推荐使用)
使用场景
- 点击某个桌面应用中的取消按钮时;
- 某个操作超过了一定的执行时间限制需要中止时;
- 多个线程做相同的事情,只要一个线程成功其它线程都可以取消时;
- 一组线程中的一个或多个出现错误导致整组都无法继续时;
- 当一个应用或服务需要停止时
- interrupt( )方法说明:interrupt()方法只是改变中断状态,不会中断一个正在运行的线程。这一方法实际完成的是,给受阻塞的线程发出一个中断信号,这样受阻线程检查到中断标识,就得以退出阻塞的状态。更确切的说,如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞,此时调用该线程的interrupt()方法,那么该线程将抛出一个 InterruptedException中断异常(该线程必须事先预备好处理此异常),从而提早地终结被阻塞状态。如果线程没有被阻塞,这时调用 interrupt()将不起作用,直到执行到wait(),sleep(),join()时,才马上会抛出 InterruptedException。
线程同步问题
同步解决方案synchronized
1.在java语言中,引入了同步锁的概念,每个对象都有一个与之关联的内部锁(排他锁),用以保证共享数据的安全性问题。
2.关键词synchronized用来给某个方法或某段代码加上一个同步锁。
3.当调用者调用此方法时,必须获得这把锁才可以调用。
4.当某个调用者获得这把锁之后,其他调用者就无法获得了。
5.当调用结束后,调用者释放这把锁,此时其他调用者才可以获得。
6.这个机制保障了某个同步方法同时只能有一个调用者
锁定方法
public class Account {private int balance = 1000;public synchronized void qu(){ // 同步方法if(balance>=1000){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}balance -= 1000;System.out.println("取了1000元,balance = " + balance);}}
}
锁定代码块
public class Account {private int balance = 1000;public void qu(){System.out.println("Account.qu");synchronized( "this" ){ // 同步块if(balance>=1000){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}balance -= 1000;System.out.println("取了1000元,balance = " + balance);}}}
}
死锁
线程同步的第二种解决方案 wait() notify()
生产者-消费者(producer-consumer)问题,也称作有界缓冲区(bounded-buffer)问题,两个线程共享一个公共的固定大小的缓冲区。其中一个是生产者,用于将消息放入缓冲区;另外一个是消费者,用于从缓冲区中取出消息。问题出现在当缓冲区已经满了,而此时生产者还想向其中放入一个新的数据项的情形,其解决方法是让生产者此时进行休眠,等待消费者从缓冲区中取走了一个或者多个数据后再去唤醒它
package test06;
//仓库(有界缓冲区)
class Storage{private int count = 0;public synchronized void set(){if(count>=5){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}count++;System.out.println("生产了一个,仓库中有:" + count);this.notify();}public synchronized void get(){if(count<=0){try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}count--;System.out.println("消费了一个,仓库中有:" + count);this.notify();}
}
//生产者
class Producer extends Thread{private Storage storage;public Producer(Storage storage){this.storage = storage;}public void run(){for(int i=0;i<50;i++){this.storage.set();}}
}
//消费者
class Customer extends Thread{private Storage storage;public Customer(Storage storage){this.storage = storage;}public void run(){for(int i=0;i<50;i++){this.storage.get();}}
}
public class Test2 {public static void main(String[] args) {Storage storage = new Storage();Producer producer = new Producer(storage);Customer customer = new Customer(storage);customer.start();producer.start();}
}