2012-10-09 21 views
7

在Callable中處理Thread.interrupted()的正確方法是什麼?我猜測可調用應該拋出一個InterruptedException;例如:在Callable中處理Thread.interrupted()的正確方法?

public class MyCallable implements Callable<Object> { 
    public Object call() { 
     Object result = null; 

     // Simulate long-running operation that calculates result 
     while (true) { 
      ... 
      if (Thread.interrupted()) { 
       throw new InterruptedException(); 
      } 
     } 

     result = ... // something produced by the long-running operation  

     return result; 
    } 
} 

這是正確的,還是有更合適的方法來處理它?謝謝。

+3

解釋'InterruptedException'的一個真實來源是[here](http://www.ibm.com/developerworks/java/library/j-jtp05236/index.html)。 –

+0

我之前讀過,但沒有提及Callable。不過,非常好的文章。 –

回答

6

編輯

一些回去後反覆復,好像你希望能夠打斷你的IO例程。對於某些NIO InterrutibleChannel類,這看起來很不錯。例如,從以下BufferedReader中讀取是可中斷的,並且會丟失InterruptedIOException。看到這裏爲more examples of the NIO code

BufferedReader in = new BufferedReader(new InputStreamReader(
    Channels.newInputStream((new FileInputStream(
     new File(...))).getChannel()))); 

然後,您可以撥打future.cancel()這會打斷你的線程,並導致IO拋出一個InterruptedIOException。如果發生這種情況,你可以而不是趕上IOException並讓它從call()方法中涓流。


如果你想回傳給了call()方法被打斷了話,我想扔InterruptedException是罰款Future。另一種選擇是從call()方法改爲return null;或其他標記對象。這通常是我在線程中斷時所做的。

有一點要記住的是,如果call()拋出InterruptedException,當你做一個future.get()它會拋出該異常的ExecutionException原因將是一個InterruptedException。如果get(long timeout, TimeUnit unit)超時,不要混淆,future.get()本身也可以丟失InterruptedException

try { 
    result = future.get(); 
} catch (ExecutionException e) { 
    if (e.getCause() instanceof InterruptedException) { 
     // call() method was interrupted 
    } 
} catch (InterruptedException e) { 
    // get was interrupted 
} 

但是,如果future.cancel(true)被稱爲那麼future.get()將拋出一個CancellationException代替。

+0

我會提供更多的上下文。我的代碼實際上並沒有使用while(true)循環 - 它從自定義的InputStream中讀取,它檢查read(byte)中的Thread.interrupted()的值。 read()方法拋出InterruptedException,以確保調用代碼(正在從流中讀取)正確關閉流。 –

+0

原來這不起作用,因爲read()只能拋出IOException。看起來像我想要的可能是InterruptedIOException。 –

+0

當然@Greg。另一個想法是使用NIO支持的「InterruptibleChannel」。 – Gray

1

這實際上取決於您希望線程如何等待get()。如果您想拋出等待線程的異常,那麼你不想throw new InterruptedException

想象

try{ 
    future.get(); 
}catch(ExecutionException ex){ 

}catch(InterruptedException em){ 

} 

如果出現任何異常你會希望它是什麼?你的情況是ExecutionException。如果你不想要ExecutionException那麼你不應該重新拋出InterruptedException。

+0

在這種情況下,我的可調用函數正在從InputStream讀取。我希望確保在Future實例上調用cancel()時關閉流(請參閱我對Gray的回答的評論)。 –

+0

你有沒有'未來'? –

+0

是的,最終我會打電話給未來(如果未來未被取消)。 –

相關問題