线程连接vs ExecutorService.awaitTermination

时间:2017-11-07 12:19:40

标签: java multithreading

我有一组线程,所有线程都需要并行执行,我必须等待所有这些线程完成。

我应该使用普通的Thread还是ExecutorService?对于ExecutorService.awaitTermination我必须给予一定的时间,我愿意等待,但Thread.join我绝对不能。

我没有对线程给出的结果做任何事情,我不需要任何futures

编辑:

    ExecutorService es = Executors.newFixedThreadPool(kThreads);
    List<Callable<Void>> calls = new LinkedList<>();

        container.forEach(
                calls.add(() -> { //creating a thread/task 
                    BufferedImage scaledBufferedImage=imageService.scale(...);

                    imageService.transferToAWS(...);
                    return null;
                })
        );
        es.invokeAll(calls); //executes each task
        es.shutdown(); //ensure that no new tasks will be accepted
        es.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); //wait for all tasks to finish

return kLinksToTheScaledImages;

5 个答案:

答案 0 :(得分:1)

寻求执行者服务。这为管理线程终止提供了许多其他好处(例如,容量扩展和执行逻辑与实际任务的分离)

答案 1 :(得分:1)

使用执行程序,您只需执行此操作。

ex.shutdown();
while (!ex.awaitTermination(1, TimeUnit.MINUTES)) {
}

其中ex是您的 ExecutorService 。在循环中,您可以检查您的线程是否仍然存在或类似的东西。

答案 2 :(得分:1)

正如您所说,您并非需要 Future这样,但您可以使用它们来等待终止。

由于您使用的是Java 8,因此可以通过

执行此操作
ExecutorService es = Executors.newFixedThreadPool(kThreads);
container.stream()
    .map(d -> createRunnable(d)) // now you have Runnables
    .map(es::submit) // now they're Futures
    .forEach(Future::get); // get() will wait for futures to finish

编辑: 我刚刚意识到流可能会阻止并行性开始,所以你需要在中间收集它们:

List<Future<?>> futures = container.stream()
    .map(d -> createRunnable(d)) // now you have Runnables
    .map(es::submit) // now they're Futures
    .collect(Collectors.toList());
futures.forEach(Future::get);

实际上,我完全理解人们对于在没有期货返回价值的情况下等待而感到困惑。 IMO,让每个未来都返回它创建的上传链接会更有意义:

String scaleAndUpload() {
    BufferedImage scaledBufferedImage=imageService.scale(...);
    imageService.transferToAWS(...);
    return linkToUploadedImage;
}

所以你会得到像

这样的东西
List<Future<?>> futures = container.stream()
    .map(d -> scaleAndUpload()) // now you have Runnables
    .map(es::submit) // now they're Futures
    .collect(Collectors.toList());
return futures.stream()
    .map(Future::get)  // collect the link when the future is finished
    .collect(Collectors.toList()); // create a list of them

答案 3 :(得分:1)

  

我应该使用普通的旧线程还是ExecutorService?

使用ExecutorService

  

对于ExecutorService.awaitTermination我必须给出一定的时间,我愿意等待,但对于Thread.join我绝对不能。

您必须查看此帖子才能正确关闭ExecutorService

How to properly shutdown java ExecutorService

这篇文章中引用了更多的替代品:

wait until all threads finish their work in java

答案 4 :(得分:0)

你可以while(!executor.isTerminated) {}。那么你不必说你愿意等多久。