java - 避免复制 CompletableFuture 的状态

标签 java completable-future

我正在尝试返回一个 CompletableFuture,它将返回来自亚马逊的响应。我的代码首先检查响应是否缓存在本地。如果是,它会返回响应,否则它会调用 Amazon。 [注意:真实版本也会缓存从亚马逊收到的响应,但我没有包含它,因为代码已经很复杂了。]

有没有办法改变我的 callAmazon 方法的实现(或以其他方式重新组织代码),这样我就不必“手动”从 amazonApi< 复制响应状态finalResponse?

我不想直接返回cacheCheck,因为我不希望调用者能够complete()它。

public CompletableFuture<Response> fetchProductList() {
    CompletableFuture<Response> finalResponse = new CompletableFuture<>();
    CompletableFuture<Response> cacheCheck = //...

    // First, see if we have a cached copy
    cacheCheck.whenComplete((response, throwable) -> {
        if (throwable == null) {
            // Cache hit. Return the cached response
            finalResponse.complete(response);
        } else {
            // Cache miss. Call Amazon
            callAmazon(finalResponse);
        }
    });
    return finalResponse;
}

private void callAmazon(CompletableFuture<Response> finalResponse) {
    CompletableFuture<Response> amazonApi = //...
    amazonApi.whenComplete((response, throwable) -> {
        // Copy the state to the `finalResponse`
        if (throwable == null) {
            finalResponse.complete(response);
        } else {
            finalResponse.completeExceptionally(throwable);
        }
    });
}

最佳答案

cacheCheck 可以抛出异常这一事实使您的要求如此复杂。

在您的情况下,我会做的是重构缓存以传递 null(如果在缓存中未找到该值)或实际的 Response(如果值在缓存中。

此外,我会修改 callAmazon 以直接返回 CompletableFuture:

private CompletableFuture<Response> callAmazon() {
    CompletableFuture<Response> amazonApi = //...
    return amazonApi;
}

这样你就可以使用thenCompose :

final CompletableFuture<Response> cacheCheck = //...
final CompletableFuture<Response> amazonResponse = callAmazon();

final CompletableFuture<Response> finalResult = 
        cachedResponse.thenCompose(cacheResult -> {
             return cacheResult == null ? amazonResponse : CompletableFuture.completedFuture(cacheResult);
    });

如果你真的需要从缓存中抛出异常,你可以使用exceptionally将异常转换为空值,然后使用 thenCompose 来决定是使用缓存值,还是调用 Amazon:

    final CompletableFuture<Response> finalResult = cachedResponse.exceptionally(e -> {
        return null;
    }).thenCompose(cacheResult -> {
        return cacheResult == null ? amazonResponse : CompletableFuture.completedFuture(cacheResult);
    });

关于java - 避免复制 CompletableFuture 的状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40728329/

相关文章:

java - Android Studio : java. lang.RuntimeException : Unable to start activity ComponentInfo. .. : java. lang.ClassCastException : java. util.ArrayList

javascript - 如何将字符串转换为 React 组件

multithreading - 与仅使用多个流相比, fork 一个流有什么优势?

java - 如何在 CompletableFuture.supplyAsync(Supplier<U> supplier) 方法中使用所需数量的工作线程设置 ForkJoinPool?

java - CompletableFuture 显示不一致的线程行为

java-8 - Tomcat 8 与 Java 8 中的 CompletableFutures

java - 如何将引用另一个 A 类型对象的 A 类型数据库对象保存到数据库中?

java - 如何在 Maven 测试运行输出中获取并行执行标识符

java - 读取文件行并存储不同类型的变量

java - 在 Java 8 中使用先前链接的 thenCompose lambda 的值