Java 以可调用的方式处理Thread.interrupted()的正确方法?
在可调用函数中处理Thread.interrupted()的正确方法是什么?我猜callable应该抛出InterruptedException;例如:Java 以可调用的方式处理Thread.interrupted()的正确方法?,java,multithreading,future,callable,Java,Multithreading,Future,Callable,在可调用函数中处理Thread.interrupted()的正确方法是什么?我猜callable应该抛出InterruptedException;例如: public class MyCallable implements Callable<Object> { public Object call() { Object result = null; // Simulate long-running operation that calcula
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;
}
}
公共类MyCallable实现可调用{
公共对象调用(){
对象结果=空;
//模拟计算结果的长期运行操作
while(true){
...
if(Thread.interrupted()){
抛出新的InterruptedException();
}
}
result=…//由长时间运行的操作生成的内容
返回结果;
}
}
这是正确的,还是有更合适的处理方法?谢谢。编辑:
经过一些来回,似乎你想能够中断你的IO例程。对于某些NIOInterrutibleChannel
类来说,这似乎是一项很好的工作。例如,从以下BufferedReader
读取是可中断的,并将抛出InterruptedIOException
。请看这里
然后,您可以调用future.cancel()
,这将中断您的线程,并导致IO抛出中断异常。如果发生这种情况,您将无法捕获IOException
,并让它从call()
方法中慢慢流出
如果您想将调用()
方法被中断的情况传回未来
,那么我认为抛出InterruptedException
是可以的。另一种选择是只返回null改为使用call()
方法中的code>或其他标记对象。如果线程被中断,我通常会这样做
需要记住的一件事是,如果call()
抛出InterruptedException
,当您执行future.get()
时,它将抛出一个ExecutionException
,而该异常的原因将是InterruptedException
。如果get(长超时,时间单位)
超时,则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
。这实际上取决于您希望线程如何等待get()
。如果不希望等待线程抛出异常,则不希望抛出新的InterruptedException
想象
try{
future.get();
}catch(ExecutionException ex){
}catch(InterruptedException em){
}
如果发生任何异常,您会期望它是什么?在您的情况下,它是一个执行异常
。如果您不希望出现执行异常
,则不应重新显示InterruptedException。我将提供更多的上下文。我的代码实际上没有使用while(true)循环-它是从一个定制的InputStream中读取,该InputStream检查read(byte)中Thread.interrupted()的值。read()方法抛出InterruptedException以确保调用代码(从流中读取)正确关闭流。结果表明,这不起作用,因为read()只能抛出IOException。看起来我想要的可能是中断异常。当然@Greg。另一个想法是使用NIO支持的interruptbleChannel
。我曾考虑过使用interruptbleChannel,但现在还不清楚该怎么做(我的代码使用标准的java.io输入/输出流)。只是为了结束循环-我的最终解决方案是实现一个自定义InputStream类,该类封装另一个InputStream并在read()中调用Thread.currentThread().isInterrupted()。如果isInterrupted()返回true,则该方法抛出InterruptedIOException。否则,它会将read()委托给包装流。它还将close()委托给包装流。我对OutputStream也做了同样的操作。在本例中,我的callable是从InputStream读取的。如果在未来实例上调用cancel(),我希望确保流关闭(请参阅我对Gray答案的评论)。您是否曾经在未来调用过get
?是的,最终我将在未来调用get()(如果未来未被取消)。好的,如果InterruptedException在调用
方法之外抛出,任何后续的get
都将看到InterruptedException,在我看来,它似乎不适合等待线程。这还假设线程池线程将清理可调用的资源。如果等待的线程将清理资源,那么获取InterruptedException可能是有意义的。@灰色如果取消导致InterruptedException,其中未来基本上被取消,则似乎在ExecutionException
之前抛出了取消异常
,这是一个真正的解释源代码InterruptedException
是。我之前读过,但它没有提到可调用。不过这篇文章很好。
try{
future.get();
}catch(ExecutionException ex){
}catch(InterruptedException em){
}