2012-10-09 12 views
7

Jaki jest właściwy sposób obsługi Thread.interrupted() w opcji Callable? Zgaduję, że wywołanie powinno wywołać wyjątek InterruptedException; na przykład:Właściwy sposób obsługi Thread.interrupted() w stanie na żądanie?

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; 
    } 
} 

Czy to jest poprawne, czy jest bardziej odpowiedni sposób na obsłużenie go? Dzięki.

+3

Jedynym prawdziwym źródłem do wyjaśnienia wyjątku "InterruptedException" jest [tutaj] (http://www.ibm.com/developerworks/java/library/j-jtp05236/index.html). –

+0

Przeczytałem to wcześniej, ale nie wspomniano o możliwości wywołania. Ale bardzo dobry artykuł. –

Odpowiedz

6

Edit:

Po jakimś tam iz powrotem, wydaje się, że chcesz być w stanie przerwać procedury IO. Wydaje się to dobrą robotą dla niektórych klas NIO InterrutibleChannel. Na przykład odczytywanie BufferedReader jest przerywalne i spowoduje wyświetlenie InterruptedIOException. Zobacz tutaj dla more examples of the NIO code.

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

Następnie można nazwać future.cancel() który powoduje przerwanie nici i powodują, że IO rzucić InterruptedIOException. Jeśli tak się stanie, możesz nie złapać IOException i niech wypływa z metody call().


Jeśli chcesz przejść z powrotem do Future że metoda call() został przerwany to myślę rzucanie InterruptedException jest w porządku. Inną opcją będzie po prostu return null; lub inny obiekt znacznikowy z metody call(). Zwykle robię to, gdy wątek został przerwany.

Jedną rzeczą do zapamiętania jest to, że jeśli call() rzuca InterruptedException, kiedy wykonujesz future.get() będzie rzucać ExecutionException i przyczyną tego wyjątku ma być InterruptedException. Nie należy mylić tego, że future.get() może sam wyrzucić samą siebie, jeśli zostanie przekroczony limit czasu wynoszący .

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

Jeśli jednak future.cancel(true) nazwano wówczas future.get() rzuci CancellationException zamiast.

+0

Podam trochę więcej kontekstu. Mój kod nie używa pętli while (true) - czyta z niestandardowego InputStream, który sprawdza wartość Thread.interrupted() w read (bajt). Metoda read() generuje wyjątek InterruptedException, aby upewnić się, że kod wywołujący (odczytany ze strumienia) poprawnie zamyka strumień. –

+0

Okazało się, że to nie zadziała, ponieważ read() może tylko rzucić wyjątek IOException. Wygląda na to, co chcę, może być wyjątek InterruptedIOException. –

+0

Sure @Greg. Innym pomysłem jest użycie 'InterruptibleChannel' obsługiwanego przez NIO. – Gray

1

To zależy od tego, w jaki sposób chcesz wątek oczekujący na get(). Jeśli ty nie chcą wątek czeka się wyjątek rzucony wtedy nie chcą throw new InterruptedException

Wyobraź

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

}catch(InterruptedException em){ 

} 

Jeśli jakikolwiek wyjątek występuje czego można się spodziewać, że będzie? W twoim przypadku jest to ExecutionException. Jeśli nie chcesz ExecutionException, nie powinieneś ponownie zgłaszać wyjątku InterruptedException.

+0

W tym przypadku moje wywoływanie czyta z InputStream. Chcę upewnić się, że strumień jest zamknięty, jeśli cancel() jest wywoływana w instancji Future (zobacz mój komentarz dotyczący odpowiedzi Graya). –

+0

Czy kiedykolwiek "dostałeś się" na przyszłość? –

+0

Tak, w końcu zadzwonię do get() na temat Przyszłości (jeśli Przyszłość nie zostanie anulowana). –

Powiązane problemy