如何在Future.cancel之后取消衍生的Callables?

时间:2017-01-24 17:05:58

标签: java multithreading

我有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}}时使用它来查找其子项并取消他们也是。但这对我来说似乎不是一个很好的解决方案,因为取消的逻辑应该放在更近的地方。

是否有处理程序/更好的方式可以给我这种灵活性?

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);
   }
}