java - 需要解释,带有嵌套 allOf 的 applyAsync 将 CompletionStage 视为已完成

标签 java java-8 completable-future

在我的应用程序中,我有 3 个 future 调用,这些调用是并行完成的,当收到其中一个调用的响应时,我还有另外 3 个请求,所有这些请求都应该在继续执行代码之前完成,正是 DeferredResult 来自 spring。

过了一段时间,我意识到页面有时会在后 3 个请求完成之前呈现。原始源代码(为简单起见省略逻辑):

public DeferredResult<String> someControllerMethod() {

    DeferredResult<String> result = new DeferredResult();

    CompletableFuture.allOf(
        future1(),
        future2(),
        future3()
    )
    .whenComplete((aVoid, throwable) -> result.setResult("something"));

    return result;
}

public CompletableFuture<?> future3() {
    return someService.asyncCall()
        .thenApplyAsync(response -> {
            ....
            return CompletableFuture.allOf(
                future4(),
                future5(),
                future6()
            );
        }
    );
}

使用 thenApplyAsync 有时 DeferredResult 在实际 future 之前完成,而更改为 thenComposeAsync 似乎可以解决问题。有人可以解释一下为什么吗?或者这是我的代码中某处的错误,它不应该这样做?

最佳答案

thenApply[Async]接受计算结果为任意值的函数。一旦返回该值, future 将用该值完成。当函数(就像在代码中一样)返回另一个 future 时,这不会为其添加额外的含义,future 将是结果值,无论是否完成,就像任何其他对象一样。

事实上,你的

public CompletableFuture<Void> future3() {
    return someService.asyncCall()
        .thenApplyAsync(response -> {
            ....
            return CompletableFuture.allOf(
                future4(),
                future5(),
                future6()
            );
        }
    );
}

该方法甚至无法编译,结果是 CompletableFuture<CompletableFuture<Void>> ,一个结果值是另一个 future 的 future 。不发现错误的唯一方法是使用更广泛的类型,例如CompletableFuture<Object>CompletableFuture<?> ,作为 future3() 的返回类型.

相比之下,thenCompose[Async]期望一个函数能够评估另一个 future ,准确地达到您期望的结果。这是“应用”和“撰写”之间的根本区别。如果您保留具体的CompletableFuture<Void> future3() 的返回类型,编译器已经引导您使用“compose”,因为只有这样才会被接受。

public CompletableFuture<Void> future3() {
    return someService.asyncCall()
        .thenComposeAsync(response -> {
            ....
            return CompletableFuture.allOf(
                future4(),
                future5(),
                future6()
            );
        }
    );
}

关于java - 需要解释,带有嵌套 allOf 的 applyAsync 将 CompletionStage 视为已完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48706612/

相关文章:

java - 更改两种类型参数边界的顺序会导致 Java 运行时错误

java - 子流中列表大小的总和

java - 传递给 CompletableFuture.allOf() 的所有 future 都会运行吗?

java - CompletableFuture 的分离异常处理

java - CompletableFuture 包装器

java - 无法解析类 java.nio.file.FileSystems

java - 将 SQLite db 与 Eclipse(Java) 和 Android Studio 结合使用

java - 使用皮肤更改比例时 libgdx 文本变得模糊

java - android:如何在哈希表中加载sqlite数据

java - Stream.reduce 始终保持并行无序流的顺序