等待 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
包含数以万计的元素。我应该使用其他方法吗?我正在寻找尽可能简单的东西
最佳答案
最简单的方法是使用 ExecutorService.invokeAll()
它可以满足您的需求。用您的话说,您需要修改或包装 ComputeDTask
实现Callable<>
,这可以给你更多的灵 active 。可能在您的应用程序中有一个有意义的 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
s 将返回空值(请参阅 Executors.callable()
的定义。可能您想要做的是轻微的重构,以便您可以得到有用的答案,或者对底层 ComputeDTask
的引用,但我无法从您的例子。
如果不清楚,请注意 invokeAll()
在完成所有任务之前不会返回。 (即,如果询问,您的 Future
集合中的所有 answers
将报告 .isDone()
。)这避免了所有手动关闭、awaitTermination 等...并允许您重用此 ExecutorService
如果需要,可以整齐地进行多个循环。
关于 SO 有几个相关的问题:
这些都不是你的问题的严格点,但它们确实为人们的想法提供了一些色彩Executor
/ExecutorService
应该使用。
关于java - ExecutorService,如何等待所有任务完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3269445/