我是Java的未来和多线程的新手。我有一个简单的问题,结果很复杂,我有许多线程(都有开放的会话),这些线程是无限开放的。每当一个线程抛出自定义异常(会话超时异常)时,我必须中断所有线程并正常关闭所有会话。我所做的是我存储线程返回的未来对象(在ArrayList中)并循环遍历它,并在一个线程抛出异常时为所有人发出future.cancel。
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,因为一些需求问题以及会话另一端的工作方式。如果我从我的callable中抛出InterruptedException,它就不会到达上面指定的catch块。如果我在我的线程中添加sleep(可以测试)并处理InterruptedException,它会在future.cancel发出后立即进入该块。我做错了什么?
答案 0 :(得分:1)
如果我从我的callable中抛出InterruptedException,它就不会到达上面指定的catch块。
不会。 InterruptedException
周围的future.get()
捕获块是指调用获取的线程被中断 - 而不是Callable
。
如果Callable
被中断并抛出InterruptedException
,那么当您致电get()
时,它将会输入ExecutionException
而e.getCause()
应为InterruptedException
}。
答案 1 :(得分:1)
Futuer#cancel(boolean)
javadoc州
如果任务已经完成,此尝试将失败 被取消,或因某些其他原因无法取消。如果 成功,并且当调用取消时,此任务尚未启动 任务永远不应该运行。如果任务已经开始,那么 mayInterruptIfRunning参数确定是否为该线程 执行此任务应该被中断,试图阻止 任务。
因此,ExecutorService
尚未执行Runnable
/ Callable
并且可以将其从队列中移除,或者它已经ExecutorService
必须调用Thread#interrupt()
并且您的Runnable
/ Callable
代码必须处理它。
通过Future
接口没有其他方法来中断线程。如果您的Runnable
无法处理中断,那么可能会发生许多事情。如果发生InterruptedException
,则会冒出ExecutorService
并将其包含在ExecutionException
中,该Future#get()
将从InterruptedException
引发。如果执行Runnable
的主题中没有Runnable
,则Runnable
将继续畅通无阻。
您应该考虑更改{{1}}来处理中断。