Java的Interrupt與執行緒中斷

我有切糕發表於2019-02-18

中斷狀態

每一個執行緒都有一個boolean屬性,表示中斷狀態,初始值為false。

中斷執行緒:Thread.interrupt()

正常情況下,只是將執行緒的中斷狀態變為true。執行緒中可以通過輪詢中斷狀態,做出相應的處理。
如果執行緒在阻塞狀態下,執行緒將退出阻塞且中斷狀態將被清除(即為false),且會丟擲InterruptException。
(IO操作忽略)

查詢中斷狀態

(1)isInterrupted(),返回當前的中斷狀態,不會改變中斷狀態。
(2)static interrupted(),返回當前中斷狀態,且會清除中斷狀態。(即第二次呼叫將返回 false)

處理InterruptedException

(1)繼續丟擲。
如果丟擲InterruptedException意味著是一個阻塞方法,那麼呼叫一個阻塞方法則意味著呼叫者也是一個阻塞方法,應該有某種策略來處理InterruptedException。
(2)捕獲InterruptedException,執行清理,再重新丟擲InterruptedException。
(3)再次呼叫interrupt()。
當由Runnable定義的任務呼叫一個可中斷的方法時,在這種情況下,不能重新丟擲InterruptedException,因為Runnable介面的run方法不允許丟擲異常。
當一個阻塞方法檢測到中斷並丟擲InterruptedException但是不能重新丟擲它,那麼應該保留中斷髮生的證據,以便呼叫棧中更高層的程式碼能知道中斷,並對中斷做出響應,該任務可以通過呼叫interrupt()以重新中斷當前執行緒來完成。

public void run() {
        try {
             while (true) {
                 Task task = queue.take(10, TimeUnit.SECONDS);
                 task.execute();
             }
         }
         catch (InterruptedException e) {
             // Restore the interrupted status
             Thread.currentThread().interrupt();
         }
    }

中斷一個不支援中斷的類

如一個IO類會阻塞執行緒,但不支援中斷。則可以寫一個新IO類,繼承Thread類,重寫interrupt方法,在interrupt中關閉IO,最後呼叫super.interrupt();

待決中斷

在進入阻塞前被中斷,被稱為待決中斷。
在呼叫阻塞方法時,會立刻丟擲InterruptException。

參考文章:多執行緒-interrupt(),isInterrupted(),interrupted() – 小路不懂2

相關文章