如何用未来中断一个线程,想要执行一些任务由未来发出的中断



我是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

最新更新