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();
}
}