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()方法,中斷狀態總是有可能會立即被重新設定。