Java併發程式設計的藝術(五)——中斷
什麼是中斷?
在Java中沒有辦法立即停止一條執行緒,然而停止執行緒卻顯得尤為重要,如取消一個耗時操作。因此,Java提供了一種用於停止執行緒的機制——中斷。
- 中斷只是一種協作機制,Java沒有給中斷增加任何語法,中斷的過程完全需要程式設計師自己實現。若要中斷一個執行緒,你需要手動呼叫該執行緒的interrupted方法,該方法也僅僅是將執行緒物件的中斷標識設成true;接著你需要自己寫程式碼不斷地檢測當前執行緒的標識位;如果為true,表示別的執行緒要求這條執行緒中斷,此時究竟該做什麼需要你自己寫程式碼實現。
- 每個執行緒物件中都有一個標識,用於表示執行緒是否被中斷;該標識位為true表示中斷,為false表示未中斷;
- 通過呼叫執行緒物件的interrupt方法將該執行緒的標識位設為true;可以在別的執行緒中呼叫,也可以在自己的執行緒中呼叫。
中斷的相關方法
-
public void interrupt()
將呼叫者執行緒的中斷狀態設為true。 -
public boolean isInterrupted()
判斷呼叫者執行緒的中斷狀態。 -
public static boolean interrupted
只能通過Thread.interrupted()呼叫。
它會做兩步操作:- 返回當前執行緒的中斷狀態;
- 將當前執行緒的中斷狀態設為false;
暫停、繼續、停止執行緒(已過時)
以下三個方法都是通過執行緒物件去呼叫。
-
suspend()
暫停呼叫者執行緒,只釋放CPU執行權,不釋放鎖。
由於在不釋放資源的情況下進入睡眠狀態,容易產生死鎖。因此已過時! -
resume()
恢復呼叫者執行緒,讓他處於就緒狀態。 -
stop()
呼叫stop後,並不會保證資源被正確地釋放,它會使程式處於不正確的狀態下。
PS:stop和interrupt的區別?
中斷的使用
要使用中斷,首先需要在可能會發生中斷的執行緒中不斷監聽中斷狀態,一旦發生中斷,就執行相應的中斷處理程式碼。
當需要中斷執行緒時,呼叫該執行緒物件的interrupt函式即可。
設定中斷監聽
Thread t1 = new Thread( new Runnable(){
public void run(){
// 若未發生中斷,就正常執行任務
while(!Thread.currentThread.isInterrupted()){
// 正常任務程式碼……
}
// 中斷的處理程式碼……
doSomething();
}
} ).start();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
正常的任務程式碼被封裝在while迴圈中,每次執行完一遍任務程式碼就檢查一下中斷狀態;一旦發生中斷,則跳過while迴圈,直接執行後面的中斷處理程式碼。
觸發中斷
t1.interrupt();
- 1
上述程式碼執行後會將t1物件的中斷狀態設為true,此時t1執行緒的正常任務程式碼執行完成後,進入下一次while迴圈前Thread.currentThread.isInterrupted()的結果為true,此時退出迴圈,執行迴圈後面的中斷處理程式碼。
安全地停止執行緒
stop函式停止執行緒過於暴力,它會立即停止執行緒,不給任何資源釋放的餘地,下面介紹兩種安全停止執行緒的方法。
迴圈標記變數
自定義一個共享的boolean型別變數,表示當前執行緒是否需要中斷。
- 中斷標識
volatile boolean interrupted = false;
- 1
- 任務執行函式
Thread t1 = new Thread( new Runnable(){
public void run(){
while(!interrupted){
// 正常任務程式碼……
}
// 中斷處理程式碼……
// 可以在這裡進行資源的釋放等操作……
}
} );
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 中斷函式
Thread t2 = new Thread( new Runnable(){
public void run(){
interrupted = true;
}
} );
- 1
- 2
- 3
- 4
- 5
迴圈中斷狀態
-
中斷標識
由執行緒物件提供,無需自己定義。 -
任務執行函式
Thread t1 = new Thread( new Runnable(){
public void run(){
while(!Thread.currentThread.isInterrupted()){
// 正常任務程式碼……
}
// 中斷處理程式碼……
// 可以在這裡進行資源的釋放等操作……
}
} );
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 中斷函式
t1.interrupt();
- 1
總結
上述兩種方法本質一樣,都是通過迴圈檢視一個共享標記為來判斷執行緒是否需要中斷,他們的區別在於:第一種方法的標識位是我們自己設定的,而第二種方法的標識位是Java提供的。除此之外,他們的實現方法是一樣的。
上述兩種方法之所以較為安全,是因為一條執行緒發出終止訊號後,接收執行緒並不會立即停止,而是將本次迴圈的任務執行完,再跳出迴圈停止執行緒。此外,程式設計師又可以在跳出迴圈後新增額外的程式碼進行收尾工作。
處理中斷
上文都在介紹如何獲取中斷狀態,那麼當我們捕獲到中斷狀態後,究竟如何處理呢?
- Java類庫中提供的一些可能會發生阻塞的方法都會拋InterruptedException異常,如:BlockingQueue#put、BlockingQueue#take、Object#wait、Thread#sleep。
- 當你在某一條執行緒中呼叫這些方法時,這個方法可能會被阻塞很長時間,你可以在別的執行緒中呼叫當前執行緒物件的interrupt方法觸發這些函式丟擲InterruptedException異常。
- 當一個函式丟擲InterruptedException異常時,表示這個方法阻塞的時間太久了,別人不想等它執行結束了。
- 當你的捕獲到一個InterruptedException異常後,亦可以處理它,或者向上丟擲。
- 丟擲時要注意???:當你捕獲到InterruptedException異常後,當前執行緒的中斷狀態已經被修改為false(表示執行緒未被中斷);此時你若能夠處理中斷,則不用理會該值;但如果你繼續向上拋InterruptedException異常,你需要再次呼叫interrupt方法,將當前執行緒的中斷狀態設為true。
- 注意:絕對不能“吞掉中斷”!即捕獲了InterruptedException而不作任何處理。這樣違背了中斷機制的規則,別人想讓你執行緒中斷,然而你自己不處理,也不將中斷請求告訴呼叫者,呼叫者一直以為沒有中斷請求。
QA
- 為什麼catch InterruptedException後會自動清除中斷狀態?
相關文章
- java面試-Java併發程式設計(五)——中斷Java面試程式設計
- Java併發程式設計的藝術Java程式設計
- Java併發程式設計藝術Java程式設計
- 《java併發程式設計的藝術》併發工具類Java程式設計
- 《java併發程式設計的藝術》Executor框架Java程式設計框架
- 《java併發程式設計的藝術》併發容器和框架Java程式設計框架
- 《java併發程式設計的藝術》原子操作類Java程式設計
- Java併發程式設計的藝術,解讀併發程式設計的優缺點Java程式設計
- 《java併發程式設計的藝術》併發底層實現原理Java程式設計
- 《java併發程式設計的藝術》執行緒池Java程式設計執行緒
- 《java併發程式設計的藝術》記憶體模型Java程式設計記憶體模型
- 【讀書筆記】Java併發程式設計的藝術筆記Java程式設計
- java併發程式設計的藝術筆記第八章——java中的併發工具類Java程式設計筆記
- 如何評價《Java 併發程式設計藝術》這本書?Java程式設計
- 【Java併發程式設計的藝術】第一章讀書筆記Java程式設計筆記
- Redux中的程式設計藝術Redux程式設計
- Java併發程式設計中的設計模式解析(一)Java程式設計設計模式
- 【Java併發程式設計的藝術】第二章讀書筆記之原子操作Java程式設計筆記
- Java 併發程式設計(八) -- AbstractQueuedSynchronizer中的NodeJava程式設計
- java 併發程式設計Java程式設計
- Java併發程式設計Java程式設計
- 併發程式設計 —— 談談執行緒中斷程式設計執行緒
- Java併發程式設計---java規範與模式下的併發程式設計1.1Java程式設計模式
- Java併發程式設計藝術第二章-----第二遍讀後記錄Java程式設計
- 【Java併發程式設計】併發程式設計大合集-值得收藏Java程式設計
- Java 併發程式設計(十) -- ReentrantLock中的SyncJava程式設計ReentrantLock
- Java 併發程式設計(六) -- ThreadPoolExecutor中的WorkerJava程式設計thread
- Java併發程式設計 - 第十一章 Java併發程式設計實踐Java程式設計
- 《程式設計師程式設計藝術》程式設計師
- .NET 中的併發程式設計程式設計
- java-併發程式設計Java程式設計
- Java併發程式設計-CASJava程式設計
- Java併發程式設計:synchronizedJava程式設計synchronized
- Java 併發程式設計解析Java程式設計
- Java併發程式設計:LockJava程式設計
- 多執行緒知識梳理(1) 併發程式設計的藝術筆記執行緒程式設計筆記
- 深入理解併發程式設計藝術之計算機記憶體模型程式設計計算機記憶體模型
- Java併發程式設計之執行緒篇之執行緒中斷(三)Java程式設計執行緒