目錄
- 1.中斷标記
- 2.中斷響應
- 3.Interrupted Exception異常
1.中斷标記
對于有些比較耗時的任務,我們往往會采用專門的工作者線程來負責其執行,如果中途要取消這類任務的執行,那麼我們就需要借助 Java 線程中斷機制。Java平台會為每個線程維護一個被稱為中斷标記的布爾型狀态變量用于表示相應線程是否接收到了中斷,中斷标記值為 true 表示相應線程收到了中斷。 目标線程可以Thread.currentThread().islnterrupted()調用來擷取該線程的中斷标記值,也可以通過Thread.interrupted()來擷取并重置(也稱清空)中斷标記值,即 Thread.interrupted()會傳回目前線程的中斷标記值并将目前線程中斷标記重置為 false。調用一個線程的interrupt()相當于将該線程(目标線程)的中斷标記置為 true。
2.中斷響應
目标線程檢查中斷标記後所執行的操作,被稱為目标線程對中斷的響應,簡稱中斷響應。設有個發起線程 originator 和目标線程 target, 那麼 target 對中斷的響應一般包括:
- 無影響。originator 調用 target.interrupt()不會對 target 的運作産生任何影響。這種情形也可以稱為目标線程無法對中斷進行響應。
- 取消任務的運作。originator調用target. interrupt()會使target在偵測到中斷(即中斷标記值為true) 那一刻所執行的任務被取消(中止),而這并不會影響target繼續處理其他任務。
- 工作者線程停止。originator調用target.interrupt()會使target終止,即target的生命周期狀态變更為TERMINATED 。
3.Interrupted Exception異常
Java 标準庫中的許多阻塞方法對中斷的響應方式都是抛出 InterruptedException 等異常,能夠響應中斷的方法通常是在執行阻塞操作前判斷中斷标志,若中斷标志值為 true則抛出InterruptedException。依照慣例,凡是抛出 InterruptedException 異常的方法,通常會在其抛出該異常之前将目前線程的線程中斷标記重置為 false。
如果發起線程給目标線程發送中斷的那一刻,目标線程已經由于執行了一些阻塞方法/操作而被暫停(生命周期狀态為 WAITING 或者 BLOCKED) 了,那麼此時 Java 虛拟機可能會設定目标線程的線程中斷标記并将該線程喚醒,進而使目标線程被喚醒後繼續執行的代碼再次得到響應中斷的機會。
是以,Java 應用層代碼通常可以通過對 InterruptedException 等異常進行處理的方式來實作中斷響應。對 InterruptedException異常的正确處理方式包括以下幾種。
- 不捕獲 lnterruptedException。如果應用代碼的某個方法調用了能夠對中斷進行響應的阻塞方法,那麼我們也可以選擇在這個方法的異常聲明 (throws) 中也加個InterruptedException。這種做法實質上是目前方法不知道如何進行中斷比較恰當,是以将“難題“抛給其上層代碼(比如這個方法的調用方)。
- 捕獲InterruptedException後重新将該異常抛出。使用這種政策通常是由于應用代碼需要捕獲 InterruptedException 并對此做一些中間處理(比如處理部分完成的任務),接着再将“難題“抛給其上層代碼 。
- 捕獲 lnterruptedException 并在捕獲該異常後中斷目前線程。這種政策實際上在捕獲到 InterruptedException 後又恢複中斷标志,這相當于目前代碼告訴其他代碼:“我發現了中斷,但我并不知道如何處理比較妥當,是以我為你保留了中斷标記,你看着辦吧!“。