轉載大佬的https://www.cnblogs.com/skywang12345/p/3479949.html、
特別好。
補充:又發現了另一位大佬的博客https://www.cnblogs.com/death00/p/11585028.html
自己的一點理解:
最終作用是中斷線程。
- Thread.interrupt(),設置當前中斷標記爲true
- Thread對象.isInterrupted(),檢測當前線程對象的中斷標記
- Thread.interrupted(),檢測當前的中斷標記,然後重置中斷標記爲false
因此interrupt中斷機制並不是真正的將當前線程中斷,而是一箇中斷標記的變化
1.首先API:
interrupt()的作用是中斷本線程。
本線程中斷自己是被允許的;其它線程調用本線程的interrupt()方法時,會通過checkAccess()檢查權限。這有可能拋出SecurityException異常。
如果本線程是處於阻塞狀態:調用線程的wait(), wait(long)或wait(long, int)會讓它進入等待(阻塞)狀態,或者調用線程的join(), join(long), join(long, int), sleep(long), sleep(long, int)也會讓它進入阻塞狀態。若線程在阻塞狀態時,調用了它的interrupt()方法,那麼它的“中斷狀態”會被清除並且會收到一個InterruptedException異常。例如,線程通過wait()進入阻塞狀態,此時通過interrupt()中斷該線程;調用interrupt()會立即將線程的中斷標記設爲“true”,但是由於線程處於阻塞狀態,所以該“中斷標記”會立即被清除爲“false”,同時,會產生一個InterruptedException的異常。
如果線程被阻塞在一個Selector選擇器中,那麼通過interrupt()中斷它時;線程的中斷標記會被設置爲true,並且它會立即從選擇操作中返回。
如果不屬於前面所說的情況,那麼通過interrupt()中斷線程時,它的中斷標記會被設置爲“true”。
中斷一個“已終止的線程”不會產生任何操作。
interrupt()只是發出中斷信號,並不能立刻結束線程。
所以對於一個線程處於阻塞狀態,通過interrupt()中斷,剛開始爲立即將中斷標記設爲"true",但由於拋異常它的中斷標記最終會被設置爲“false”。同時,會產生一個InterruptedException的異常。通過捕獲這個異常進行結束
其次對於一個運行狀態的線程,那麼通過interrupt()中斷線程時,它的中斷標記會被設置爲“true”。所以配合Thread對象.isInterrupted()進行結束
即可。
總而言之結合兩種情況,最終要實現中斷所有線程可以在這樣:
@Override
public void run() {
try {
// 1. isInterrupted()保證,只要中斷標記爲true就終止線程。
while (!isInterrupted()) {
// 執行任務...
}
} catch (InterruptedException ie) {
// 2. InterruptedException異常保證,當InterruptedException異常產生時,線程被終止。
}
}