我有ExecutorService
我提交n Callable
。在这些n Callable
中的每一个中,我生成了新的Callable
,这些ExecutorService
被提交到同一个java.util.concurrent.TimeoutException
。
当我在各自的Callable
的前n Future.get()
中遇到Future.cancel(true)
时,Callable
Callable
Callable
。由于取消了Callable
s,我还需要取消我提交的任务。
我可以这样做的一种方法是将生成的{{1}}存储在调用堆栈中某个位置的列表中,并在取消{{1}}时使用它来查找其子项并取消他们也是。但这对我来说似乎不是一个很好的解决方案,因为取消的逻辑应该放在更近的地方。
是否有处理程序/更好的方式可以给我这种灵活性?
答案 0 :(得分:3)
当我在各自的Future.get()的前n个Callables中遇到java.util.concurrent.TimeoutException时,我在Callable上执行Future.cancel()。由于取消了Callables,我还需要取消我提交的任务。
当您致电future.cancel(false)
时,它只会在作业尚未运行时停止执行。在这种情况下,您不会遇到问题,因为没有创建“子作业”。
所以我假设您正在谈论future.cancel(true)
,如果作业已在运行,它将中断线程。重要的是要意识到此中断仅会影响抛出InterruptedException
的少数方法 - 如Thread.sleep(...)
,obj.wait(...)
等。否则您将需要测试用于代码中的中断标志。例如:
while (!Thread.currentThread().isInterrupted()) {
...
}
我要做的是让你的每个工作都保留一份它产生的Future
个“子工作”的清单。当它捕获InterruptedException
或者当它注意到它的线程中断标志已被设置时,它可以在它分叉的所有作业上调用future.cancel(true)
。
类似的东西:
final List<Future<...>> subJobs = new ArrayList<>();
...
while (true) {
if (Thread.currentThread().isInterrupted()) {
cleanupSubJobs(subJobs);
break;
}
try {
Thread.sleep(...);
} catch (InterruptedException ie) {
// always a good pattern
Thread.currentThread.interrupt();
cleanupSubJobs(subJobs);
return;
}
...
if (weNeedSubJob) {
subJobs.add(threadPool.submit(...));
}
}
...
private void cleanupSubJobs(List<Future<...>> subJobs) {
for (Future<...> subJob : subJobs) {
subJob.cancel(true);
}
}