謎題84:被粗暴地中斷
阿新 • • 發佈:2018-10-24
不能 是否 ren 狀態 class ring ear 為什麽 sys
果你運行該程序,你會發現並不是這樣。但是它也沒有打印 Not interrupted:
false,它打印的是 Interrupted: false。
看起來該程序好像不能確定線程是否被中斷了。當然,這種看法是毫無意義的。
實際上發生的事情是,Thread.interrupted 方法第一次被調用的時候返回了
true,並且清除了線程的中斷狀態,所以在 if-then-else 語句的分支中第 2 次
調用該方法的時候,返回的就是 false。調用 Thread.interrupted 方法總是會
清除當前線程的中斷狀態。方法的名稱沒有為這種行為提供任何線索,而對於
5.0 版本,在相應的文檔中有一句話概要地也同樣具有誤導性地敘述道:“測試
當前的線程是否中斷”[Java-API]。所以,可以理解為什麽很多程序員都沒有意
識到 Thread.interrupted 方法會對線程的中斷狀態造成影響。
Thread 類有 2 個方法可以查詢一個線程的中斷狀態。另外一個方法是一個名為
isInterrupted 的實例方法,而它不會清除線程的中斷狀態。如果使用這個方法
重寫程序,它就會打印出我們想要的結果 true:
在下面這個程序中,一個線程試圖中斷自己,然後檢查中斷是否成功。它會打印
什麽呢?
public class SelfInterruption { public static void main(String[ ] args) { Thread.currentThread().interrupt(); if(Thread.interrupted()) { System.out.println("Interrupted: " + Thread.interrupted()); } else{ System.out.println("Not interrupted: " + Thread.interrupted()); } } }
雖然一個線程中斷自己不是很常見,但這也不是沒有聽說過的。當一個方法捕捉
到了一個 InterruptedException 異常,而且沒有做好處理這個異常的準備時,
那麽這個方法通常會將該異常重新拋出(rethrow)。但是由於這是一個“被檢
查的異常”,所以只有在方法聲明允許的情況下該方法才能夠將異常重新拋出。
如果不能重新拋出,該方法可以通過中斷當前線程對異常“再構建”(reraise)。
這種方式工作得很好,所以這個程序中的線程中斷自己應該是沒有任何問題的。
所以,該程序應該進入 if 語句的第一個分支,打印出 Interrupted: true。如
false,它打印的是 Interrupted: false。
看起來該程序好像不能確定線程是否被中斷了。當然,這種看法是毫無意義的。
實際上發生的事情是,Thread.interrupted 方法第一次被調用的時候返回了
true,並且清除了線程的中斷狀態,所以在 if-then-else 語句的分支中第 2 次
調用該方法的時候,返回的就是 false。調用 Thread.interrupted 方法總是會
清除當前線程的中斷狀態。方法的名稱沒有為這種行為提供任何線索,而對於
5.0 版本,在相應的文檔中有一句話概要地也同樣具有誤導性地敘述道:“測試
識到 Thread.interrupted 方法會對線程的中斷狀態造成影響。
Thread 類有 2 個方法可以查詢一個線程的中斷狀態。另外一個方法是一個名為
isInterrupted 的實例方法,而它不會清除線程的中斷狀態。如果使用這個方法
重寫程序,它就會打印出我們想要的結果 true:
public class SelfInterruption { public static void main(String[ ] args) { Thread.currentThread().interrupt(); if(Thread.currentThread().isInterrupted()) { System.out.println("Interrupted: " + Thread.currentThread().isInterrupted()); }else{ System.out.println("Not interrupted: " + Thread.currentThread().isInterrupted()); } } }
這個謎題的教訓是:不要使用 Thread.interrupted 方法,除非你想要清除當前
線程的中斷狀態。如果你只是想查詢中斷狀態,請使用 isInterrupted 方法。這
裏給 API 設計者們的教訓是方法的名稱應該用來描述它們主要功能。根據
Thread.interrupted 方法的行為,它的名稱應該是 clearInterruptStatus,因
為相對於它對中斷狀態的改變,它的返回值是次要的。特別是當一個方法的名稱
並不完美的時候,文檔是否能清楚地描述它的行為就顯得非常重要了。
謎題84:被粗暴地中斷