Java并发编程实战————恢复中断
中斷是一種協作機制,一個線程不能強制其他線程停止正在執行的操作而去執行其他操作。
什么是中斷狀態?
線程類有一個描述自身是否被中斷了的boolean類型的狀態,可以通過調用 .isInterrupted() 方法來查看。官方解釋如下:
簡單來說,這個方法如果返回 true ,那么表示線程已經被中斷。
恢復中斷
這里提到的 “恢復中斷” 絕對不是 “從中斷中恢復” 的意思!
在《Java并發編程實戰》一書第五章 p78頁,首次提到了這個恢復中斷的概念,而當我看到第七章的時候才明白這里為什么要恢復中斷。
因為中斷是一種協作機制,當一個線程阻塞時,我們需要通過另一個線程調用阻塞線程的 interrupt() 方法,來請求阻塞線程取消任務。最簡單的阻塞方法就是 Thread.sleep() , 我們來看一下我寫的一個簡單的例子:
public class Demo_01 {public static void main(String[] args) throws InterruptedException {Thread myTh = new Thread(new TaskDemo());myTh.start();TimeUnit.SECONDS.sleep(3);// 中斷myTh線程myTh.interrupt();} }class TaskDemo implements Runnable {@Overridepublic void run() {try {TimeUnit.SECONDS.sleep(10);} catch (InterruptedException e) {System.out.println("捕獲到中斷異常,當前線程的中斷狀態是:" + Thread.currentThread().isInterrupted());System.out.println("即將恢復中斷... ...");Thread.currentThread().interrupt();System.out.println("中斷恢復!中斷狀態已經是:" + Thread.currentThread().isInterrupted());}} }執行結果是:
我們可以看到,interrupt()方法會將線程的中斷狀態置為true,而任務被中斷的時候不僅會拋出一個InterruptedException異常,還會清除中斷狀態!
這個問題在書中第七章 P114 有所說明:
阻塞庫方法,例如Thread.sleep和Object.wait等,都會檢查線程何時中斷,并且在發現中斷時提前返回。它們在響應中斷時執行的操作包括:清除中斷狀態;拋出InterruptedException,表示阻塞操作由于中斷而提前結束。
上面的程序中,由于TaskDemo實現Runnable接口,在面對中斷請求的時候,無法向上層拋出,必須捕獲,如果沒有在catch塊中調用interrupt()方法,那么中斷狀態將在清除之后被上層邏輯 “屏蔽”。書中強調,一個健壯的任務執行方法,應該能夠正確處理中斷請求,而不是屏蔽。
因此,如果不想任務執行時出現的中斷被屏蔽,就必須將線程的中斷狀態恢復,換句話說,就是再次將線程的中斷狀態置為true!
因為有點繞,所以大多數人可能完全無視了這個問題,導致我在搜索這個恢復中斷的問題時,頁面里全都是些如何從中斷的狀態中恢復過來,真的很無語。
總結
調用線程的interrupt()方法可以向一個阻塞中的線程發出中斷請求,其原理就是將線程的中斷狀態設置為true。
阻塞的線程在收到中斷請求的時候,會執行兩步操作:清除中斷狀態,拋出中斷異常(InterruptedException)。
這就導致了在一些無法向調用者繼續拋出中斷異常的情況下,如實現了Runnable接口,必須在run()方法內部進行中斷異常的捕獲,從而導致了上層調用者可能無法正確獲得線程的中斷狀態,導致沒有相應的處理措施,即為中斷被屏蔽。
因此,在這種情況下,為了避免任務內部屏蔽了中斷請求(注意,屏蔽中斷請求并不意味著任務沒有響應中斷),需要通過在catch塊中重新調用任務所在線程的interrupt()方法,恢復到中斷狀態,來告訴上層調用者,“我是一個已經被中斷的線程”。
綜上,就是關于《Java并發編程實戰》中“恢復中斷”的相關理解,歡迎文末留言。
總結
以上是生活随笔為你收集整理的Java并发编程实战————恢复中断的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java ssh cpu_初学Java
- 下一篇: 个人生活助手app_美居App 6版重磅