原文:www.spring4all.comjava
線程中斷是線程的標誌位屬性。而不是真正終止線程,和線程的狀態無關。線程中斷過程表示一個運行中的線程,經過其餘線程調用了該線程的 interrupt()
方法,使得該線程中斷標誌位屬性改變。git
深刻思考下,線程中斷不是去中斷了線程,偏偏是用來通知該線程應該被中斷了。具體是一個標誌位屬性,到底該線程生命週期是去終止,仍是繼續運行,由線程根據標誌位屬性自行處理。github
調用線程的 interrupt()
方法,根據線程不一樣的狀態會有不一樣的結果。web
下面新建 InterruptedThread 對象,代碼以下:spring
/** * 一直運行的線程,中斷狀態爲 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 併發編程的藝術》