等待ExecutorService的所有任务完成的最简单方法是什么?我的任务主要是计算性的,所以我只想运行大量的作业——每个核心一个。现在,我的设置如下所示:
Executors服务=Executors.newFixedThreadPool(2);
for(DataTable singleTable:uniquePhrases){
执行(新的ComputeDTask(singleTable));
}
试一试{
等一下;
}
捕捉(中断异常e){
e、 printStackTrace();
}
ComputeDTask实现可运行。这似乎可以正确执行任务,但代码在wait()上崩溃,出现IllegalMonitorStateException。这是奇怪的,因为我玩了一些玩具的例子,它似乎工作
uniquePhrases包含数万个元素。我应该用另一种方法吗?我在寻找尽可能简单的东西
最简单的方法是使用ExecutorService.invokeAll(),它可以在一行程序中实现您想要的功能。按照您的说法,您需要修改或包装ComputeDTask以实现Callable<&燃气轮机,这可以给您带来更多的灵活性。可能在你的应用程序中有一个有意义的Callable.call()实现,但是如果不使用Executors.Callable(),这里有一种方法可以包装它
Executors服务=Executors.newFixedThreadPool(2);
列表<;可调用<;对象>&燃气轮机;todo=新阵列列表<;可调用<;对象>&燃气轮机;(singleTable.size());
for(DataTable singleTable:uniquePhrases){
add(Executors.callable(newcomputedtask(singleTable));
}
列表<;未来<;对象>&燃气轮机;answers=es.invokeAll(todo);
正如其他人所指出的,如果合适,您可以使用invokeAll()的超时版本。在本例中,answers将包含一组Futures,它们将返回null(请参见Executors.callable()的定义)。可能您想做的是进行一次轻微的重构,这样您就可以得到一个有用的答案,或者一个对底层计算任务的引用,但我无法从您的示例中看出
如果不清楚,请注意,invokeAll()将在所有任务完成之前不会返回(即,如果询问,answers集合中的所有Futures将报告.isDone())这避免了所有手动关机、等待终止等操作,并允许您在需要时将此ExecutorService灵活地重复使用多个周期
因此,有几个相关问题:
-
如何等待所有线程完成
-
从java线程返回值
-
invokeAll()不愿意接受集合<;可调用<;t>;>
-
我需要同步吗
对于您的问题,这些都不是严格意义上的,但它们确实为人们如何使用Executor/ExecutorService提供了一些色彩