线程中断是线程的标志位属性。而不是真正终止线程,和线程的状态无关。线程中断过程表示一个运行中的线程,经过其余线程调用了该线程的 interrupt()
方法,使得该线程中断标志位属性改变。java
深刻思考下,线程中断不是去中断了线程,偏偏是用来通知该线程应该被中断了。具体是一个标志位属性,到底该线程生命周期是去终止,仍是继续运行,由线程根据标志位属性自行处理。git
调用线程的 interrupt()
方法,根据线程不一样的状态会有不一样的结果。github
下面新建 InterruptedThread 对象,代码以下:web
/** * 一直运行的线程,中断状态为 true * * @author Jeff Lee @ bysocket.com * @since 2018年02月23日19:03:02 */ public class InterruptedThread implements Runnable { @Override // 能够省略 public void run() { // 一直 run while (true) { } } public static void main(String[] args) throws Exception { Thread interruptedThread = new Thread(new InterruptedThread(), "InterruptedThread"); interruptedThread.start(); TimeUnit.SECONDS.sleep(2); interruptedThread.interrupt(); System.out.println("InterruptedThread interrupted is " + interruptedThread.isInterrupted()); TimeUnit.SECONDS.sleep(2); } }
运行 main 函数,结果以下:编程
InterruptedThread interrupted is true
代码详解:安全
interrupt()
方法,中断状态置为 true,但不会影响线程的继续运行另外一种状况,新建 InterruptedException 对象,代码以下:websocket
/** * 抛出 InterruptedException 的线程,中断状态被重置为默认状态 false * * @author Jeff Lee @ bysocket.com * @since 2018年02月23日19:03:02 */ public class InterruptedException implements Runnable { @Override // 能够省略 public void run() { // 一直 sleep try { TimeUnit.SECONDS.sleep(10); } catch (java.lang.InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) throws Exception { Thread interruptedThread = new Thread(new InterruptedException(), "InterruptedThread"); interruptedThread.start(); TimeUnit.SECONDS.sleep(2); // 中断被阻塞状态(sleep、wait、join 等状态)的线程,会抛出异常 InterruptedException // 在抛出异常 InterruptedException 前,JVM 会先将中断状态重置为默认状态 false interruptedThread.interrupt(); System.out.println("InterruptedThread interrupted is " + interruptedThread.isInterrupted()); TimeUnit.SECONDS.sleep(2); } }
运行 main 函数,结果以下:网络
InterruptedThread interrupted is false java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method)
代码详解:并发
小结下线程中断:框架
代码:https://github.com/JeffLi1993/java-concurrency-core-learning
好比在 IDEA 中强制关闭程序,当即中止程序,不给程序释放资源等操做,确定是不正确的。线程终止也存在相似的问题,因此须要考虑如何终止线程?
上面聊到了线程中断,能够利用线程中断标志位属性来安全终止线程。同理也可使用 boolean 变量来控制是否须要终止线程。
新建 ,代码以下:
/** * 安全终止线程 * * @author Jeff Lee @ bysocket.com * @since 2018年02月23日19:03:02 */ public class ThreadSafeStop { public static void main(String[] args) throws Exception { Runner one = new Runner(); Thread countThread = new Thread(one, "CountThread"); countThread.start(); // 睡眠 1 秒,通知 CountThread 中断,并终止线程 TimeUnit.SECONDS.sleep(1); countThread.interrupt(); Runner two = new Runner(); countThread = new Thread(two,"CountThread"); countThread.start(); // 睡眠 1 秒,而后设置线程中止状态,并终止线程 TimeUnit.SECONDS.sleep(1); two.stopSafely(); } private static class Runner implements Runnable { private long i; // 终止状态 private volatile boolean on = true; @Override public void run() { while (on && !Thread.currentThread().isInterrupted()) { // 线程执行具体逻辑 i++; } System.out.println("Count i = " + i); } public void stopSafely() { on = false; } } }
从上面代码能够看出,经过 while (on && !Thread.currentThread().isInterrupted())
代码来实现线程是否跳出执行逻辑,并终止。可是疑问点就来了,为啥须要 on
和 isInterrupted()
两项一块儿呢?用其中一个方式不就好了吗?答案在下面
on
经过 volatile 关键字修饰,达到线程之间可见,从而实现线程的终止。但当线程状态为被阻塞状态(sleep、wait、join 等状态)时,对成员变量操做也阻塞,进而没法执行安全终止线程isInterrupted();
只去解决阻塞状态下的线程安全终止。不少好友介绍,若是用 Spring 栈开发到使用线程或者线程池,那么尽可能使用框架这块提供的线程操做及框架提供的终止等
资料: 《Java 并发编程的艺术》