线程的中断

129 阅读3分钟

「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战

1. 什么是中断(中断协商)?

线程不应该由其他线程来强行中断或者停止,所以后续废弃了Thread.stop, Thread.suspend, Thread.resume方法。

中断只是一种协作机制,中断的过程需要开发者自己实现。

如果想要中断一个线程,那么可以调用线程的interrupt方法,将中断标识位设置为true,接着自己通过代码去不断的检测当前线程的标识位。如果是true,那么表示要求这条线程中断。**并不是立刻中断(停止)。**直到执行完成之后才停止

中断有主要的三个方法:

public void interrupt()实例方法:只会将中断状态设置为true,并不会停止线程

public static boolean interrupted()静态方法:Thread.interrupted()判断线程是否被中断,1. 返回线程的中断状态,2. 将当前线程的中断状态设置为false连续调用两次的结果可能不一致

public static boolean interrupted() {    return currentThread().isInterrupted(true);}

public boolean isInterrupted()实例方法:判断当前线程是否被中断。

public boolean isInterrupted() {    return isInterrupted(false);}

中断的例子:第一种(因为volatile的可见性)指另一条线程能够观察到另一条线程的状态。

public static volatile boolean isStop = false;		new Thread(() -> {           while (true){               if (isStop){                   System.out.println("线程结束");                   break;               }               System.out.println("等待线程中...");           }        }).start();        try {            Thread.sleep(5);        } catch (InterruptedException e) {            e.printStackTrace();        }        new Thread(()->{            isStop = true;        }).start();

另一种方法是使用原子类AtomicBoolean等。例子如下:(比较优雅的程序退出机制,利用原子类的原子性可见性

AtomicBoolean atomicBoolean = new AtomicBoolean(false);

new Thread(() -> {   while (true){       if (atomicBoolean.get()){           System.out.println("线程结束");           break;       }       System.out.println("等待线程中...");   }}).start();try {    Thread.sleep(1);} catch (InterruptedException e) {    e.printStackTrace();}new Thread(()->{    atomicBoolean.set(true);}).start();

最后一种:

Thread thread = new Thread(() -> {    while (true) {        if (Thread.currentThread().isInterrupted()) { //判断是否为true            System.out.println("线程结束");            break;        }        System.out.println("等待线程中...");    }}, "thread");thread.start();try {    Thread.sleep(1);} catch (InterruptedException e) {    e.printStackTrace();}new Thread(()->{    thread.interrupt(); //修改thread线程的中断标志为true}).start();

中断可能出现的问题(中断后,明明结束或者抛异常,但是依然再打印,无法停止)

Thread thread = new Thread(() -> {    while (true) {        if (Thread.currentThread().isInterrupted()) {  //状态为True            System.out.println("线程结束");            break;        }        System.out.println("等待线程中...");        try {            Thread.sleep(500); //当进行休眠之后,线程会认为被外部中断,设置标识位为false,抛出异常之后继续打印不停止。        } catch (InterruptedException e) {            Thread.currentThread().interrupt();  //让线程重新设置为true,抛异常之后才会停止            e.printStackTrace();        }    }}, "thread");thread.start();try {    Thread.sleep(1);} catch (InterruptedException e) {    e.printStackTrace();}new Thread(()->{    thread.interrupt(); //修改thread线程的中断标志为true}).start();

原因:

在Thread类中的interrupt()上,描述着

* #join(long, int)}, {@link #sleep(long)}, or {@link #sleep(long, int)},* methods of this class, then its interrupt status will be cleared and it* will receive an {@link InterruptedException}.

如果采用sleep(long)或者sleep(long, int)方法进行中断的时候,interrupt这个方法所设置的状态就会被清除,他就会接受一个InterruptedException异常。

所以,如果要解决这个问题,可以在睡眠之后,重新将他的状态设置为true,中断线程。