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());