1. 程式人生 > >Oracle官方併發教程之中斷

Oracle官方併發教程之中斷

原文連結譯文連結譯者: 蘑菇街-小寶   校對:樑海艦
中斷是給執行緒的一個指示,告訴它應該停止正在做的事並去做其他事情。一個執行緒究竟要怎麼響應中斷請求取決於程式設計師,不過讓其終止是很普遍的做法。這是本文重點強調的用法。

一個執行緒通過呼叫對被中斷執行緒的Thread物件的interrupt()方法,傳送中斷訊號。為了讓中斷機制正常工作,被中斷的執行緒必須支援它自己的中斷(即要自己處理中斷)

中斷支援

執行緒如何支援自身的中斷?這取決於它當前正在做什麼。如果執行緒正在頻繁呼叫會拋InterruptedException異常的方法,在捕獲異常之後,它只是從run()方法中返回。例如,假設在SleepMessages的例子中,關鍵的訊息迴圈線上程的Runnable物件的run方法中,程式碼可能會被修改成下面這樣以支援中斷:

for (int i = 0; i < importantInfo.length; i++) {
    // Pause for 4 seconds
    try {
       Thread.sleep(4000);
    } catch (InterruptedException e) {
       // We've been interrupted: no more messages.
      return;
 }
 // Print a message
 System.out.println(importantInfo[i]);
}

許多會拋InterruptedException異常的方法(如sleep()),被設計成接收到中斷後取消它們當前的操作,並在立即返回。

如果一個執行緒長時間執行而不呼叫會拋InterruptedException異常的方法會怎樣? 那它必須週期性地呼叫Thread.interrupted()方法,該方法在接收到中斷請求後返回true。例如:

for (int i = 0; i < inputs.length; i++) {
    heavyCrunch(inputs[i]);
    if (Thread.interrupted()) {
        // We've been interrupted: no more crunching.
        return;
    }
}

在這個簡單的例子中,程式碼只是檢測中斷,並在收到中斷後退出執行緒。在更復雜的應用中,丟擲一個InterruptedException異常可能更有意義。

if (Thread.interrupted()){
   throw new InterruptedException();
}

這使得中斷處理程式碼能集中在catch語句中。

中斷狀態標記

中斷機制通過使用稱為中斷狀態的內部標記來實現。呼叫Thread.interrupt()設定這個標記。當執行緒通過呼叫靜態方法Thread.interrupted()檢測中斷時,中斷狀態會被清除。非靜態的isInterrupted()方法被執行緒用來檢測其他執行緒的中斷狀態,不改變中斷狀態標記。

按照慣例,任何通過丟擲一個InterruptedException異常退出的方法,當拋該異常時會清除中斷狀態。不過,通過其他的執行緒呼叫interrupt()方法,中斷狀態總是有可能會立即被重新設定。