Java SupplySync等待所有CompletableFutures完成
我正在运行下面的一些异步任务,需要等待它们全部完成。我不知道为什么,但是Java SupplySync等待所有CompletableFutures完成,java,asynchronous,java-8,completable-future,Java,Asynchronous,Java 8,Completable Future,我正在运行下面的一些异步任务,需要等待它们全部完成。我不知道为什么,但是join()没有强制等待所有任务,代码继续执行而不等待。连接流没有按预期工作有什么原因吗 CompletableFutures列表只是一个映射SupplySync的流 List<Integer> items = Arrays.asList(1, 2, 3); List<CompletableFuture<Integer>> futures = items
join()
没有强制等待所有任务,代码继续执行而不等待。连接流没有按预期工作有什么原因吗
CompletableFutures列表只是一个映射SupplySync的流
List<Integer> items = Arrays.asList(1, 2, 3);
List<CompletableFuture<Integer>> futures = items
.stream()
.map(item -> CompletableFuture.supplyAsync(() -> {
System.out.println("processing");
// do some processing here
return item;
}))
.collect(Collectors.toList());
我能够使用futures.forEach(CompletableFuture::join)实现等待代码>但我想知道为什么我的流方法不起作用。此代码:
CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()]))
.thenApply(ignored -> futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList()));
不等待期货
中的所有期货完成。它所做的是创建一个新的未来,它将等待futures
中的所有异步执行在其自身完成之前完成(但在所有这些未来完成之前不会阻止)。当这一切完成后,您的然后apply
代码将运行。但是allOf()
将立即返回而不阻塞
这意味着代码中的futures.stream().map(CompletableFuture::join).collect(Collectors.toList())
仅在所有异步执行完成后运行,这与您的目的背道而驰。join()
调用将立即返回。但这并不是更大的问题。您面临的挑战是allOf()。thenApply()
不会等待异步执行完成。它只会创造另一个不会阻碍的未来
最简单的解决方案是使用第一个管道并映射到整数列表:
List<Integer> results = items.stream()
.map(item -> CompletableFuture.supplyAsync(() -> {
System.out.println("processing " + item);
// do some processing here
return item;
}))
.collect(Collectors.toList()) //force-submit all
.stream()
.map(CompletableFuture::join) //wait for each
.collect(Collectors.toList());
最后一个语句中的join()
调用立即返回,因为对包装器(allOf()
)future的join()
调用将等待传递给它的所有未来完成。这就是为什么当您可以使用第一种方法时,我看不到这样做的原因。您是否尝试等待CompletableFuture.allOf().thenApply()的结果completable future?你只需要创建一个新的未来,而不需要对它进行任何操作。这不是我的CompletableFuture.allOf()应该做的吗?它加入了每个应该阻止的期货,直到所有期货都完成。我不知道.allOf(…)。然后apply(…)
方法是如何失败的。唯一缺少的是链接另一个join()
以获取结果列表(这意味着等待它)。@Holger在allOf
之后传递给thenApply()
的回调直到所有的期货包装在allOf()
中完成后才会运行。这意味着在该回调中对这些未来调用join()
,就强迫系统等待结果而言没有任何意义(如果所有join()
都从已完成的未来中获取结果,则不会导致等待)。我意识到这个句子的措辞可以更好,但这就是我的意思。我已经建议了您在上一个代码片段中建议的join()
调用,但我不喜欢对该方法的双重调用。
List<Integer> results = items.stream()
.map(item -> CompletableFuture.supplyAsync(() -> {
System.out.println("processing " + item);
// do some processing here
return item;
}))
.collect(Collectors.toList()) //force-submit all
.stream()
.map(CompletableFuture::join) //wait for each
.collect(Collectors.toList());
List<Integer> reuslts = futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList());
//wrapper future completes when all futures have completed
CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()]))
.join();
//join() calls below return immediately
List<Integer> result = futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList());