ExecutorService,如何等待所有任务完成 [英] ExecutorService, how to wait for all tasks to finish

查看:274
本文介绍了ExecutorService,如何等待所有任务完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

What is the simplest way to to wait for all tasks of ExecutorService to finish? My task is primarily computational, so I just want to run a large number of jobs - one on each core. Right now my setup looks like this:

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 。这很奇怪,因为我玩了一些玩具示例,它似乎工作。

ComputeDTask implements runnable. This appears to execute the tasks correctly, but the code crashes on wait() with IllegalMonitorStateException. This is odd, because I played around with some toy examples and it appeared to work.

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

uniquePhrases contains several tens of thousands of elements. Should I be using another method? I am looking for something as simple as possible

推荐答案

最简单的方法是使用 ExecutorService.invokeAll() 可以在单行中完成您想要的任务。按照你的说法,你需要修改或包装 ComputeDTask 来实现 Callable<> ,这可以给你相当多的灵活性。可能在你的应用程序中有一个有意义的 Callable.call()的实现,但如果不使用 Executors.callable( )

The simplest approach is to use ExecutorService.invokeAll() which does what you want in a one-liner. In your parlance, you'll need to modify or wrap ComputeDTask to implement Callable<>, which can give you quite a bit more flexibility. Probably in your app there is a meaningful implementation of Callable.call(), but here's a way to wrap it if not using 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 ,它将返回空值(参见<$的定义) c $ c> Executors.callable()。你可能想要做的是轻微的重构,这样你就可以得到一个有用的答案,或者对底层 ComputeDTask <的引用/ code>,但我无法从你的例子中看出。

As others have pointed out, you could use the timeout version of invokeAll() if appropriate. In this example, answers is going to contain a bunch of Futures which will return nulls (see definition of Executors.callable(). Probably what you want to do is a slight refactoring so you can get a useful answer back, or a reference to the underlying ComputeDTask, but I can't tell from your example.

如果不清楚,请注意 invokeAll() 在完成所有任务之前不会返回。(即答案中的所有 Future s collection将报告 .isDone()。这可以避免所有手动关机,awaitTermination等...并允许你重复使用 ExecutorService 如果需要,可以整齐地进行多个周期。

If it isn't clear, note that invokeAll() will not return until all the tasks are completed. (i.e., all the Futures in your answers collection will report .isDone() if asked.) This avoids all the manual shutdown, awaitTermination, etc... and allows you to reuse this ExecutorService neatly for multiple cycles, if desired.

SO上有一些相关的问题:

There are a few related questions on SO:

从java线程返回值

invokeAll()不愿意接受集合< Callable< t>>

我需要同步吗?

这些都不是严格意义上的问题,但它们确实提供了一些关于人们如何思考的颜色执行者 / ExecutorService 应该被使用。

None of these are strictly on-point for your question, but they do provide a bit of color about how folks think Executor/ExecutorService ought to be used.

这篇关于ExecutorService,如何等待所有任务完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆