我是Java中未来和多线程的新手。我有一个简单的问题,结果证明很复杂,我有许多线程(其中都有打开的会话),它们是无限开放的。每当一个线程抛出自定义异常(会话上的超时异常)时,我都必须中断所有线程并正常关闭所有会话。我所做的是将线程返回的未来对象(在 ArrayList 中)存储并遍历它,并在一个线程抛出异常时发出 future.cancel for all。
private static void futureCancel()
{
for(int i=0;i<numberStreams;i++)
{
Future<String> future=futureList.get(i);
try{
future.cancel(true);
future.get();
}
catch(InterruptedException e)
{
System.out.println("In interrupted block!");
} catch (ExecutionException e) {
e.printStackTrace();
}
}
return;
}
这里的问题是,由于一些需求问题以及会话另一端的工作方式,我无法在我的线程代码中添加 InterruptedException。如果我从可调用对象中抛出中断异常,它不会到达上面指定的 catch 块。如果我在我的线程中添加睡眠(可以进行测试)并处理中断异常,它会在发出 future.cancel 后立即进入该块。我做错了什么?
Futuer#cancel(boolean)
javadoc 状态
如果任务已经完成,并且已经 已取消,或由于其他原因无法取消。如果 成功,并且调用取消时此任务尚未启动,此 任务不应运行。如果任务已启动,则 mayInterruptIfRunning 参数确定线程是否 应中断执行此任务以尝试停止 任务。
因此,要么ExecutorService
没有执行Runnable
/Callable
并且可以将其从队列中删除,要么它已经执行并且ExecutorService
必须调用Thread#interrupt()
并且您的Runnable
/Callable
代码必须处理它。
没有其他方法可以通过Future
接口中断线程。如果您的Runnable
无法处理中断,则可能会发生许多事情。如果发生InterruptedException
,它会冒泡到ExecutorService
并包裹在从Future#get()
扔出的ExecutionException
中。如果在执行Runnable
的线程中没有发生InterruptedException
,您的Runnable
将继续不受阻碍。
您确实应该考虑更改Runnable
来处理中断。
如果我从我的可调用对象中抛出一个中断异常,它不会到达上面指定的 catch 块。
不会的。future.get()
周围的InterruptedException
捕获块是当调用get的线程被中断时 - 而不是您的Callable
。
如果您的Callable
被打断并抛出InterruptedException
那么当您调用get()
时,它将进入ExecutionException
并且e.getCause()
应该InterruptedException
。