中斷的原理
Java中斷機制是一種協作機制,中斷並不能直接終止另一個線程,而需要被中斷的線程自己處理中斷。
java.lang.Thread類提供了幾個方法來操作這個中斷狀態,這些方法包括:
public static boolean interrupted()
測試當前線程是否已經中斷。線程的中斷狀態由該方法清除。
public boolean isInterrupted()
測試線程是否已經中斷。線程的中斷狀態不受該方法的影響。
public void interrupt()
中斷線程
線程1通過調用interrupt方法將線程2的中斷狀態置為true,2可以在合適的時候調用interrupted或isInterrupted來檢測狀態並做相應的處理。
類庫中的有些類的方法也可能會調用中斷:
如FutureTask中的cancel方法,如果傳入的參數為true,它將會在正在運行異步任務的線程上調用interrupt方法,
如果正在執行的異步任務中的代碼沒有對中斷做出響應,那么cancel方法中的參數將不會起到什么效果;
又如ThreadPoolExecutor中的shutdownNow方法會遍歷線程池中的工作線程並調用線程的interrupt方法來中斷線程,
所以如果工作線程中正在執行的任務沒有對中斷做出響應,任務將一直執行直到正常結束。
thread.stop():
線程會馬上停止,但是可能導致數據不同步,或者資源得不到回收的問題而且stop已經標注為作廢方法,所以使用一定要慎重。
中斷的處理
interrupt()方法僅僅是在當前線程中打了一個停止的標識將中斷標志修改為true,並沒有真正的停止線程:
如果在此基礎上進入堵塞狀態(sleep(),wait(),join()),馬上就會拋出一個InterruptedException,
且中斷標志被清除,重新設置為false,線程退出。
如果遇到的是可中斷的阻塞方法拋出InterruptedException:
可以繼續向上層拋出該異常。
若有時候不太方便在方法上拋出InterruptedException,比如要實現的某個接口中的方法簽名上沒有throws InterruptedException,
這時就可以捕獲可中斷方法的InterruptedException並且恢復異常(重新設置中斷)。
中斷的響應:
有些程序可能一檢測到中斷就立馬將線程終止,有些可能是退出當前執行的任務,繼續執行下一個任務……
作為一種協作機制,這要與中斷方協商好,當調用interrupt會發生些什么都是事先知道的,如做一些事務回滾操作,一些清理工作,一些補償操作等。
若不確定調用某個線程的interrupt后該線程會做出什么樣的響應,那就不應當中斷該線程。
中斷的使用
- 點擊某個桌面應用中的取消按鈕時;
- 某個操作超過了一定的執行時間限制需要中止時;
- 多個線程做相同的事情,只要一個線程成功其它線程都可以取消時;
- 一組線程中的一個或多個出現錯誤導致整組都無法繼續時;
- 當一個應用或服務需要停止時。