Java 如何在将来取消生成的可调用项。取消?

Java 如何在将来取消生成的可调用项。取消?,java,multithreading,Java,Multithreading,我有一个ExecutorService,我向其提交nCallables。在这些nCallables中,我生成了新的Callables,它们被提交到相同的ExecutorService。 当我在其各自的Future.get()中的前n个可调用的s上遇到java.util.concurrent.TimeoutException时,我会对该可调用的执行Future.cancel(true)。我还需要取消我提交的任务,因为这些任务已被取消Callables 我可以这样做的一种方法是将生成的Callabl

我有一个
ExecutorService
,我向其提交n
Callable
s。在这些n
Callable
s中,我生成了新的
Callable
s,它们被提交到相同的
ExecutorService
。 当我在其各自的
Future.get()
中的前n个
可调用的
s上遇到
java.util.concurrent.TimeoutException
时,我会对该
可调用的
执行
Future.cancel(true)
。我还需要取消我提交的任务,因为这些任务已被取消
Callable
s

我可以这样做的一种方法是将生成的
Callable
存储在调用堆栈中某个位置的列表映射中,在取消
Callable
的同时,使用它查找其子项并取消它们。但这对我来说似乎不是一个很好的解决方案,因为取消的逻辑应该在更近的地方

有没有更好的方法可以给我这种灵活性

当我在前n个可调用项各自的Future.get()上遇到java.util.concurrent.TimeoutException时,我会对该可调用项执行Future.cancel()。由于这些已取消的可调用项,我还需要取消我提交的任务

调用
future.cancel(false)
时,仅当作业尚未运行时,才会停止作业的执行。在这种情况下,您不会有问题,因为没有创建“子作业”

因此,我假设您谈论的是
未来。cancel(true)
,如果作业已经在运行,它将中断线程。必须认识到,此中断只影响引发
InterruptedException
的少数方法,如
Thread.sleep(…)
obj.wait(…)
等。。否则,您将需要测试代码中的中断标志。例如:

while (!Thread.currentThread().isInterrupted()) {
   ...
}
我要做的是让你的每一份工作都保留一份它产生的未来的“子工作”的列表。当它捕捉到一个
中断异常
或者当它注意到它的线程中断标志已经设置时,它就可以对它分叉的所有作业调用
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);
   }
}
final List subbobs=new ArrayList();
...
while(true){
如果(Thread.currentThread().isInterrupted()){
清理子作业(子作业);
打破
}
试一试{
睡眠(…);
}捕获(中断异常ie){
//总是一个好的模式
Thread.currentThread.interrupt();
清理子作业(子作业);
返回;
}
...
如果(weNeedSubJob){
subbobs.add(threadPool.submit(…);
}
}
...
私有无效清除子作业(列表子作业){
for(未来主题:主题){
subJob.cancel(true);
}
}

似乎根
可调用的
应该协调其派生的
可调用的
s。因此,当它接收到取消中断时,它应该在其“子对象”上调用
cancel
。注意让callablea在同一池中阻塞它们自己的callables。这就是死锁的秘诀。@SotiriosDelimanolis您的意思是说我应该在根目录中调用一个try-catch块来检测ThreadInterruptedException以进行清理吗?Future.cancel()是否确保触发此异常?是的,只是一般情况。例如,请参阅。
Future#cancel
通常通过中断执行器服务中执行工作的线程来实现。你应该听听,并把它传播给孩子们。谢谢你的回答。在我的第二级可调用函数中引入无限while循环似乎不是一个简单的方法。它基本上将subbob提交到线程池,然后等待subbob返回。然而,我看到Future.get()抛出了一个InterruptedException。如果我在第二级Callable中发现了这一点,我可以取消那里的所有子任务。