CompletableFuture 直接链接与单独链接时的行为不同

CompletableFuture behaves differently when chained directly vs individually

伙计们,我一直在我的项目中使用 CompletableFuture,我遇到了一个奇怪的行为。我想了解这种行为。请帮忙

场景 1: 在下面的代码中,输出是 我来自 supply 我是第一个 thenApply 我是第二个 thenApply .. 正如预期的那样

public void callAll(){
        String calculatedDistance = listBuildComp().stream()
                .map(CompletableFuture::join)
                .collect(Collectors.joining());
        System.out.println(calculatedDistance);
    }
    private List<CompletableFuture<String>> listBuildComp(){
        List<CompletableFuture<String>> result = new ArrayList<>();
        result.add(buildComp());
        return result;
    }

    private CompletableFuture<String> buildComp(){
        CompletableFuture<String> workFlowWithServices =
                CompletableFuture.supplyAsync( () -> "I am from supply ")
        .thenApply( x -> {
            return x.concat(" I am the first thenApply ");
        })
        .thenApply( x -> {
            return x.concat(" I am the second thenApply ");
        });
        return workFlowWithServices;
    }

场景 2: 当更改以下方法时,输出为 I am from supply 。经过进一步调查,我发现其余两个 thenApply 在自己的线程中运行

private CompletableFuture<String> buildComp(){
        CompletableFuture<String> workFlowWithServices =
                CompletableFuture.supplyAsync( () -> "I am from supply ");
        
        workFlowWithServices.thenApply( x -> {
            return x.concat(" I am the first thenApply ");
        });
        
        workFlowWithServices.thenApply( x -> {
            return x.concat(" I am the second thenApply ");
        });
        return workFlowWithServices;
    }

我对场景 2 感兴趣的原因是假设您正在链接 2 个任务,那么场景 1 没问题,但假设您想要链接 50 个任务,那么该方法将变得太大.在这种情况下,我想首先将每个调用提取到一个方法中,但如果需要,最终提取到一个 class 中,但我无法完成场景 2 的所有这些原因。

想知道为什么方案 2 以不同的方式运行的概念或想法,以及是否有办法让它像方案 1 一样运行。请分享您的知识。谢谢。

首先,你有 哪个线程将执行那些 thenApply,它很可能是 main

然后在您的示例中,您构建一个 CompletableFuture:

CompletableFuture<String> workFlowWithServices =
       CompletableFuture.supplyAsync( () -> "I am from supply ");

链接一些动作:

    workFlowWithServices.thenApply( x -> {
        System.out.println("executing");
        return x.concat(" I am the first thenApply ");
    })

   ...

但是你忽略那个thenApply的结果(这也是一个CompletableFuture<String>)。当你 join 时,你 joinworkFlowWithServices 上,当它完成时,将 return "I am from supply "。完毕。您不查询(您完全忽略)thenApply 中后续操作的结果,因此它们确实执行了,但结果消失了。

我不明白是什么阻止了你构建这样的东西,例如:

 private static CompletableFuture<String> buildComp2(){
    CompletableFuture<String> one =
            CompletableFuture.supplyAsync( () -> "I am from supply ");

    CompletableFuture<String> two = one.thenApply( x -> {
        System.out.println("executing");
        return x.concat(" I am the first thenApply ");
    });

    CompletableFuture<String> three = two.thenApply( x -> {
        return x.concat(" I am the second thenApply ");
    });
    return three;
}