ExecutorService awaitTermination方法未按预期执行

时间:2014-12-04 18:38:02

标签: java concurrency threadpool executorservice

我试图用Java编写一个同时执行一系列任务的进程,等待完成任务,然后将整个进程标记为完成。每个任务都有自己的信息,包括个别任务何时完成。我正在使用ExecutorService进行流程,并将流程的本质归结为如下:

List<Foo> foos = getFoos();
ExecutorService executorService = Executors.newFixedThreadPool(foos.size());
for (Foo foo : foos) {
    executorService.execute(new MyRunnable(foo));
}

executorService.shutdown();

try {
    executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
} catch (InterruptedException e) {
    // log the error.
}

completeThisProcess();

每个MyRunnable对象都有一个运行方法,该方法进行Web服务调用,然后将调用结果写入数据库,包括调用完成的时间。 completeThisProcess方法只是简单地将整个过程的状态与过程完成的时间一起写入。

我遇到的问题是,当我在进程完成后查看数据库时,completeThisProcess方法显然能够在所有MyRunnable完成之前执行。我注意到,在最后一次MyRunnable任务完成之前,从completeThisProcess方法写入的时间偶尔会超过20-30秒。

我写的这个过程有什么明显错误吗?也许我没有正确理解ExecutorService,但我认为awaitTermination方法应该确保所有MyRunnable实例都已经完成了他们的运行方法(假设它们完全没有例外),这将导致所有子任务在整个过程的完成时间之前具有完成时间。

1 个答案:

答案 0 :(得分:2)

如果要等待所有线程返回,则可以信任以下方法。 使你的线程类实现Callable接口而不是Runnable(如果Callable run方法将返回一些值。让它返回threadName。

创建Callable对象列表并使用invokeAll方法,该方法将等待所有线程返回。对于以下代码,假设线程类名称为MyCallable。

ExecutorService executorService = Executors.newFixedThreadPool(foos.size());
List<Callable> tasks = new ArrayList<>();
for (Foo foo : foos) {
  tasks.add(new MyCallable(foo));
 }
 executorService.invokeAll(tasks);

invokeAll如果要使用它,则返回将来对象的列表。

OR

您可以使用CountDownLatch

CountDownLatch cdl = new CountDownLatch(foo.size);

使用cdl.countDown()方法使其在run方法中倒计时。 在for循环之后使用cdl.await然后它将等待,直到cdl变为零。

标题