我有一组线程,它们都需要并行执行,并且我必须等待所有线程完成。
我应该使用普通的旧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;
最佳答案
正如您所说,您不需要 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);
实际上,我完全理解人们对 future 没有返回值而必须等待感到困惑。 IMO,让每个 future 返回它创建的上传链接会更有意义:
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
关于java - 线程加入与 ExecutorService.awaitTermination,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47157838/