我使用 ExecutorService 来执行任务。该任务可以递归地创建提交给同一ExecutorService的其他任务,这些子任务也可以这样做。
我现在有一个问题,我想等到所有任务都完成(即所有任务都完成并且他们没有提交新任务)后再继续。
我无法在主线程中调用 ExecutorService.shutdown(),因为这会阻止 ExecutorService 接受新任务。
如果 shutdown 没有被调用,那么调用 ExecutorService.awaitTermination() 似乎什么都不做。
所以我有点卡在这里。 ExecutorService 看到所有工作人员都处于空闲状态并不是那么难,不是吗?我能想到的唯一不优雅的解决方案是直接使用 ThreadPoolExecutor 并每隔一段时间查询它的 getPoolSize()。真的没有更好的办法吗?
最佳答案
这确实是 Phaser 的理想人选。 Java 7 即将推出这个新类。它是一个灵活的 CountdonwLatch/CyclicBarrier。您可以在 JSR 166 Interest Site 获得稳定版本.
它是更灵活的 CountdownLatch/CyclicBarrier 的方式是因为它不仅能够支持未知数量的参与方(线程),而且还可以重复使用(这就是阶段部分的来源)
对于您提交的每项任务,您都会注册,当该任务完成时,您就会到达。这可以递归完成。
Phaser phaser = new Phaser();
ExecutorService e = //
Runnable recursiveRunnable = new Runnable(){
public void run(){
//do work recursively if you have to
if(shouldBeRecursive){
phaser.register();
e.submit(recursiveRunnable);
}
phaser.arrive();
}
}
public void doWork(){
int phase = phaser.getPhase();
phaser.register();
e.submit(recursiveRunnable);
phaser.awaitAdvance(phase);
}
编辑:感谢@depthofreality 在我之前的示例中指出竞争条件。我正在更新它,以便执行线程仅等待当前阶段的推进,因为它阻塞递归函数完成。
在 arrives == registers 的数量之前,阶段编号不会跳闸。由于在每个递归调用调用 register 之前,当所有调用都完成时会发生阶段增量。
关于Java ExecutorService : awaitTermination of all recursively created tasks,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4958330/