2011-10-25 46 views
2

我正在閱讀Java Concurrency in Practice第7章。Java:從代碼中調用可中斷方法

在一節中提到的方法沒有自己的取消策略,但調用了可以被中斷的方法,本書有以下內容可以說。

的活動,不支持取消,但仍然叫中斷 阻斷方法將不得不打電話給他們在一個循環中,重試時 中斷是detected.In這種情況下,他們應該保存在本地 中斷狀態並恢復它在返回之前, 而不是立即捕獲InterruptedException。

我還沒有完全理解這一點。

這是不是說,如果我在我的方法中調用Thread.sleep,我將不得不在循環中調用它?

任何人都可以解釋爲什麼它應該這樣做嗎?

+0

這裏給出一個合理的解釋:http://stackoverflow.com/questions/7751690/noncancelable-task-that-restores-interruption-before-exit – Cole

回答

4

我打電話了Thread.sleep在我的方法,我將不得不調用它在一個循環的東西?

Thread.sleep()噹噹前線程中斷(由另一個線程)時將拋出InterruptedException。如何對此做出反應是您的選擇。如果你想睡覺,不管是否有人試圖打斷你,那麼是的,你必須在try-catch塊周圍建立某種循環。也許你應該使用時鐘(例如System.nanoTime())來檢查你睡了多久,被拋出的異常前,然後繼續睡等

注意InterruptedException拋出僅的剩餘時間,如果另一個線程已中斷當前線程,通過調用(current)Thread.interrupt()。它本身不會發生,所以一般來說,你不需要在睡覺或類似的東西周圍建立任何循環。通常,線程只會因爲一個很好的原因而中斷(例如,應用程序關閉),所以您可能想要支持取消/中斷,除非沒有特殊原因。例如,「特殊原因」可能是寫入I/O設備,並試圖保證所有數據都將被寫入,而不管取消嘗試。

0

據我所知:長時間運行的服務本身不能或不應該被打斷,正在調用其他可以中斷的方法。所以這個長時間運行的服務應該能夠檢測到這一點並通過方法或標誌報告它。但它應該能夠再次嘗試操作,而不是隻拋出InterruptedException。

要調用阻塞方法,當前執行被阻塞,並且正在等待阻塞方法返回一個值。這可以在一個循環中完成。那麼你知道方法調用是否成功,或者調用的方法是否中斷。

0

我沒有這本書。但據我瞭解,如果一個活動中斷(順便說睡眠不是一箇中斷信號,但你可以通過中斷信號從睡眠中喚醒線程),活動需要按順序保存當前的動態數據(中斷狀態)恢復自己並從之前的狀態恢復。例如;

//Let's say you have integer data named "a"... 
a = 45646; 

//Normally after interruption, and terminating the activity data a is currently 
//referencing @memory will be released... 

//If you want to continue using data in a you have to save it somewhere 
// persistant(Let's say a file) 
void onInterruptionDetected() 
{ 
    saveToSomeFile(a, "temp.txt"); 
} 

//After re-execution of activity(Assuming we need a's previous data in order to 
// continue...), we can recover a's data(which is 45646) in previous interruption... 
void onResumeDetected() 
{ 
    a = loadFromFile("temp.txt") 
} 

希望這有助於我仍然困有可能是一個錯誤:)

1

一些解釋第一:

線程的中斷狀態基本上是一個布爾標誌,它被設置爲「真」的interrupt()。 該標誌的當前狀態可以是閱讀使用Thread.currentThread().isInterrupted()

如果中斷操作(如Object.wait()Thread.sleep())發現中斷標誌設置 會拋出InterruptedException,並在同一時間明確(設置爲「假」)的標誌,它看起來是這樣的:

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

請注意並記住Thread.interrupted()隱式清除中斷標誌! 這意味着,在您執行catch(InterruptedException ie) {...}時,線程本身並不知道它已被中斷。

那麼,讓我們來看看兩個例子:

首先它支持取消任務的一個例子。 在這裏,我們並不真正關心多遠被中止前的任務來進行:

public void run() { 

    int x = 0; 

    try { 

     while (x < 10) { 
     Thread.sleep(1000); // Some interruptible operation 
     x++; 
     } 

     System.out.println("x = " + x); 

    } catch (InterruptedException ie) { 

     System.out.println("Interrupted: x = " + x); 

     // We know we've been interrupted. 
     // Let the caller know it, too: 
     Thread.currentThread().interrupt(); 
    } 

    } 

此代碼試圖如果它不被中斷數從0 x到10,這將完成輸出「X = 10" 。 但是,如果線程在兩者之間中斷,則將拋出InterruptedException,從而中止正在執行的增加x的任務。 在這種情況下,根據線程何時中斷,輸出可能是「中斷:x = 0」到「中斷:x = 9」之間的任何內容。

請注意,從 退出之前恢復線程的中斷標誌被認爲是一種好的做法,否則此run()方法的調用方將看不到中斷狀態。

現在,如果它是至關重要的是,我們的任務完全執行,從而使輸出將始終以「X = 10」,這意味着任務不支持取消,我們需要另一種方法:

public void run() { 
    int x = 0; 

    boolean wasInterrupted = false; // <- This is the local variable to store the interruption status 

    while (x < 10) { 

     wasInterrupted = wasInterrupted || Thread.interrupted(); // not really needed in this case, but for the sake of completeness... 

     try { 

     Thread.sleep(1000); // <- Some interruptible operation 

     } catch (InterruptedException e) { 
     wasInterrupted = true; 
     } 

     x++; 
    } 

    System.out.println("x = " + x); 

    if (wasInterrupted) { 
     Thread.currentThread().interrupt(); 
    } 

    } 

在這種情況下,我們甚至在InterruptedException之後繼續處理,直到任務完成。 爲了保持良好,如果我們檢測到中斷,我們將該條件存儲在wasInterrupted中,以便我們可以在從該方法返回之前正確設置中斷標誌。

這就是由

意味着要在本地保存中斷狀態,只是在返回之前恢復。

它說,「應該」,因爲我們沒有嚴格要求來處理中斷這種方式 - 我們可能也只是忽略任何InterruptedException ,只是完成我們的任務,然後返回。但這並不是上面提到的良好做法,並且在某些情況下可能會造成麻煩。