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

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

Executors服务=Executors.newFixedThreadPool(2);
for(DataTable singleTable:uniquePhrases){
执行(新的ComputeDTask(singleTable));
}
试一试{
等一下;
} 
捕捉(中断异常e){
e、 printStackTrace();
}

ComputeDTask实现可运行。这似乎可以正确执行任务,但代码在wait()上崩溃,出现IllegalMonitorStateException。这是奇怪的,因为我玩了一些玩具的例子,它似乎工作

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

最简单的方法是使用ExecutorService.invokeAll(),它可以在一行程序中实现您想要的功能。按照您的说法,您需要修改或包装ComputeDTask以实现Callable&lt&燃气轮机,这可以给您带来更多的灵活性。可能在你的应用程序中有一个有意义的Callable.call()实现,但是如果不使用Executors.Callable(),这里有一种方法可以包装它

Executors服务=Executors.newFixedThreadPool(2);
列表<可调用<对象&gt&燃气轮机;todo=新阵列列表<可调用<对象&gt&燃气轮机;(singleTable.size());
for(DataTable singleTable:uniquePhrases){
add(Executors.callable(newcomputedtask(singleTable));
}
列表<未来<对象&gt&燃气轮机;answers=es.invokeAll(todo);

正如其他人所指出的,如果合适,您可以使用invokeAll()的超时版本。在本例中,answers将包含一组Futures,它们将返回null(请参见Executors.callable()的定义)。可能您想做的是进行一次轻微的重构,这样您就可以得到一个有用的答案,或者一个对底层计算任务的引用,但我无法从您的示例中看出

如果不清楚,请注意,invokeAll()将在所有任务完成之前不会返回(即,如果询问,answers集合中的所有Futures将报告.isDone())这避免了所有手动关机、等待终止等操作,并允许您在需要时将此ExecutorService灵活地重复使用多个周期

因此,有几个相关问题:

  • 如何等待所有线程完成

  • 从java线程返回值

  • invokeAll()不愿意接受集合<可调用<t>&gt

  • 我需要同步吗

对于您的问题,这些都不是严格意义上的,但它们确实为人们如何使用Executor/ExecutorService提供了一些色彩

发表评论