ExecutorService,如何等待所有任务完成

新手上路,请多包涵

等待 ExecutorService 的所有任务完成的最简单方法是什么?我的任务主要是计算性的,所以我只想运行大量作业——每个核心一个。现在我的设置如下所示:

 ExecutorService es = Executors.newFixedThreadPool(2);
for (DataTable singleTable : uniquePhrases) {
    es.execute(new ComputeDTask(singleTable));
}
try{
    es.wait();
}
catch (InterruptedException e){
    e.printStackTrace();
}

ComputeDTask 实现可运行。这似乎可以正确执行任务,但代码在 wait()IllegalMonitorStateException 上崩溃。这很奇怪,因为我尝试了一些玩具示例并且它似乎有效。

uniquePhrases 包含数万个元素。我应该使用另一种方法吗?我正在寻找尽可能简单的东西

原文由 george smiley 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 594
1 个回答

最简单的方法是使用 ExecutorService.invokeAll() 它可以在单行中执行您想要的操作。用你的话说,你需要修改或包装 ComputeDTask 来实现 Callable<> ,这可以给你更多的灵活性。可能在您的应用程序中有 Callable.call() 的有意义的实现,但如果不使用 Executors.callable() --- ,这里有一种包装它的方法。

 ExecutorService es = Executors.newFixedThreadPool(2);
List<Callable<Object>> todo = new ArrayList<Callable<Object>>(singleTable.size());

for (DataTable singleTable: uniquePhrases) {
    todo.add(Executors.callable(new ComputeDTask(singleTable)));
}

List<Future<Object>> answers = es.invokeAll(todo);

正如其他人指出的那样,如果合适,您可以使用 invokeAll() 的超时版本。在此示例中, answers 将包含一堆 Future 将返回空值(参见 Executors.callable() 的定义)。轻微重构,以便您可以获得有用的答案,或对底层 ComputeDTask 的引用,但我无法从您的示例中看出。

如果不清楚,请注意 invokeAll() 在所有任务完成之前不会返回。 (即,您的 answers 集合中的所有 Future s 将报告 .isDone() 如果被问到的话。)这避免了所有手动关机等的终止…如果需要,允许您在多个周期中整齐地重复使用这个 ExecutorService

SO 上有几个相关问题:

这些都不是严格针对您的问题,但它们确实提供了一些关于人们如何思考的颜色 Executor / ExecutorService 应该被使用。

原文由 andersoj 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题