2013-01-03 114 views
0

我正想通過Oracle的Java教程的主題,我看到這個例子java的混亂

源:http://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html

如果一個線程進入一個很長一段時間,而不必調用一個方法拋出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; 
} 

教程添加: 中斷機構被使用被稱爲中斷狀態的內部標誌實現。調用Thread.interrupt設置此標誌。當一個線程通過調用靜態方法Thread.interrupted來檢查中斷時,中斷狀態被清除。一個線程用於查詢另一個線程的中斷狀態的非靜態isInterrupted方法不會更改中斷狀態標誌。

按照慣例,任何通過拋出InterruptedException退出的方法都會清除中斷狀態。但是,通過另一個線程調用中斷,可能會立即再次設置中斷狀態。

現在我很困惑。它何時發生?如果有中斷,不應該線程收到InterruptedException?

當有人可能使用這些方法檢查他們的代碼? Thread.interrupt(該標誌)是靜態的,所以通過上面的檢查,我們實際上檢查是否有任何踏板已經中斷?即使是這樣,根據教程,當一個線程通過調用靜態方法Thread.interrupted檢查中斷時,中斷狀態被清除。任何通過拋出InterruptedException而退出的方法在清除中斷狀態時會清除中斷狀態

因此,我是否錯過了某些東西?或者這只是有用的,如果某個線程收到中斷,但不檢查它,或不扔它?

+0

問題的癥結在於你要麼手動檢查你的線程的中斷狀態,要麼你會處理一個'InterruptedException'。 – Perception

回答

2

並非所有的方法,在Thread,拋出InterrupedException s。這在睡眠和等待中,或者任何耗時的方法中最常見。這是Java實現它的方式。 (sleep(...)native代碼,所以我不能告訴你的來源。)

例如:

try { 
    Thread.sleep(1000); // one sec 
} catch(InterruptedException e){ 
} 

但你不能強迫包括一個簡單的for循環,在try..catch條款。

如果你的子類Thread,你應該遵循約定,張貼。


關於第二個問題,關於static方法,這裏的內部代碼:

public static boolean interrupted() { 
    return currentThread().isInterrupted(true); 
} 

所以你可以看到,它只是設置,在當前線程的實例

+0

感謝MouseEvent,但從我的理解,如果有睡眠或等待,並且我們做t.interrupt,它會拋出InterruptedException。你可以給我一個例子嗎。 – Athena

1

很多次一個線程正在做很多等待或阻止。在幾乎所有這些情況下,執行阻塞的方法都支持InterruptedException。一些示例:

  1. Thread.sleep(millis);
  2. obj = arrayBlockingQueue.take();
  3. obj.wait();

引用的文章指出的是,如果你的線程沒有被阻塞,意味着沒有支持InterruptedException的方法,那麼你有責任檢查你的線程是否被中斷。這通過測試Thread.interrupted()來完成。

方法Thread.interrupt()其實不是靜態的,而是從另一個線程調用來中斷該線程。請參閱以下內容:

Thread.interrupt()

這是否有意義?

5

這Thread.interrupted實現

public static boolean interrupted() { 
    return currentThread().isInterrupted(true); 
} 

private native boolean isInterrupted(boolean ClearInterrupted); 

,你可以看到它可以檢查/復位只有當前線程的中斷狀態。如果它不是靜態的,你可以在其他線程上調用它,並重置API不允許的狀態。