首页 > 解决方案 > 调用使用 CompletableFuture 的 thenAccept() 的方法

问题描述

我有一个返回 DeferredResult 类型的对象的 rest API 函数。

import org.springframework.web.context.request.async.DeferredResult;

public DeferredResult<Object> apiMethod{
CompletableFuture<Object> future = someMethod();
final DeferredResult<Object> response = new DeferredResult<>(); 

future.thenAccept(){
    //logic to populate response
}

return response;
}

我正在编写一个函数,它将调用 apiMethod() 并使用它的响应。我总是最终得到一个空响应,因为在 future.thenAccept () 中填充了响应。有没有办法处理这个?

标签: javaspring-bootcompletable-future

解决方案


问题是该方法在thenAccept异步运行时继续执行。在您调用 之后thenAccept,该方法只会在response之后返回,与它是否已经填充无关。

想象一下下面的简单代码:

    public static void main(String[] args) {
        AtomicReference<String> result = new AtomicReference<>(null);
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            for (int i = 0; i < 100_000_000; i++) {}
            return "Hello World!";
        });
        future.thenAccept(s -> {
            result.compareAndSet(null, s);
        });
        System.out.println(result.get());
    }

您可能希望"Hello World!"打印出来,但事实并非如此;它打印出来null。这是同样的问题:主线程打印该值,该值将在某个时候异步更新。您可以通过加入未来来解决此问题:

    public static void main(String[] args) {
        AtomicReference<String> result = new AtomicReference<>(null);
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            for (int i = 0; i < 100_000_000; i++) {}
            return "Hello World!";
        });
        CompletableFuture<Void> end = future.thenAccept(s -> {
            result.compareAndSet(null, s);
        });
        end.join();
        System.out.println(result.get());
    }

现在,当我们加入异步未来链,或者更确切地说是设置值的一个未来时,我们将看到主线程打印出来,"Hello World!"因为它会等待未来完成。

现在你只需要在你的代码中应用这个修复。


推荐阅读