我目前正在使用CompletableFuture supplyAsync()方法向公共线程池提交一些任务。下面是代码片段:
final List<CompletableFuture<List<Test>>> completableFutures = resolvers.stream()
.map(resolver -> supplyAsync(() -> task.doWork()))
.collect(toList());
CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[completableFutures.size()])).join();
final List<Test> tests = new ArrayList<>();
completableFutures.stream()
.map(completableFuture -> completableFuture.getNow())
.forEach(tests::addAll);我想知道下面的代码与上面的代码有什么不同。我从下面的代码中删除了父completableFuture,并为每个completableFuture添加了join(),而不是getNow():
final List<CompletableFuture<List<Test>>> completableFutures = resolvers.stream()
.map(resolver -> supplyAsync(() -> task.doWork()))
.collect(toList());
final List<Test> tests = new ArrayList<>();
completableFutures.stream()
.map(completableFuture -> completableFuture.join())
.forEach(tests::addAll);我在spring服务中使用了这个,线程池耗尽有问题。我们非常感谢您提出的任何建议。
发布于 2018-09-20 21:46:26
首先,.getNow()不起作用,因为这个方法需要一个回退值作为未来还没有完成的情况下的参数。既然您假设将来会在这里完成,那么您也应该使用join()。
然后,在线程耗尽方面没有区别,因为在这两种情况下,您都在等待所有作业完成,然后再继续,这可能会阻塞当前线程。
避免这种情况的唯一方法是重构代码,使其不期望同步得到结果,而是在所有作业完成后安排后续处理操作完成。然后,使用allOf就变得有意义了:
final List<CompletableFuture<List<Test>>> completableFutures = resolvers.stream()
.map(resolver -> supplyAsync(() -> task.doWork()))
.collect(toList());
CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture<?>[0]))
.thenAccept(justVoid -> {
// here, all jobs have been completed
final List<Test> tests = completableFutures.stream()
.flatMap(completableFuture -> completableFuture.join().stream())
.collect(toList());
// process the result here
});顺便说一句,关于集合上的toArray方法,我推荐阅读Arrays of Wisdom of the Ancients…
https://stackoverflow.com/questions/52370888
复制相似问题