等待ExecutorService所有任务完成的最简单方法是什么?我的任务主要是计算性的,所以我只想运行大量的作业——每个核心上都有一个。现在我的设置是这样的:
ExecutorService es = Executors.newFixedThreadPool(2);
for (DataTable singleTable : uniquePhrases) {
es.execute(new ComputeDTask(singleTable));
}
try{
es.wait();
}
catch (InterruptedException e){
e.printStackTrace();
}
ComputeDTask实现了runnable。这似乎正确地执行了任务,但代码在wait()时崩溃,并出现IllegalMonitorStateException。这是奇怪的,因为我玩了一些玩具的例子,它似乎工作。
uniquePhrases包含数万个元素。我应该用另一种方法吗?我在寻找一些尽可能简单的东西
IllegalMonitorStateException的根本原因:
抛出该异常,表示线程试图等待对象的监视器,或通知其他线程等待对象的监视器而不拥有指定的监视器。
在代码中,您刚刚在ExecutorService上调用了wait(),但没有拥有锁。
下面的代码将修复IllegalMonitorStateException
try
{
synchronized(es){
es.wait(); // Add some condition before you call wait()
}
}
遵循以下方法中的一种来等待所有已提交给ExecutorService的任务的完成。
Iterate through all Future tasks from submit on ExecutorService and check the status with blocking call get() on Future object
Using invokeAll on ExecutorService
Using CountDownLatch
Using ForkJoinPool or newWorkStealingPool of Executors(since java 8)
Shutdown the pool as recommended in oracle documentation page
void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
If you want to gracefully wait for all tasks for completion when you are using option 5 instead of options 1 to 4, change
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
to
a while(condition) which checks for every 1 minute.