「这是我参与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,中断线程。