简体   繁体   中英

Invoking a method which uses CompletableFuture's thenAccept()

I have a rest API function which returns an object of type DeferredResult.

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;
}

I am writing a function which will invoke apiMethod() and use its response. I always end up getting a null response because response is populated in future.thenAccept (). Is there a way to handle this?

The problem is that the method continues the execution while thenAccept runs async. After you call thenAccept , the method just returns response afterwards, independent of if it's already populated.

Imagine the following simple code:

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

You may expect that "Hello World!" is printed, which is not the case; it prints out null . Here's the same problem: the main-thread prints the value, which will be updated async somewhen. You can fix this by joining the future:

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

Now when we join the async future chain, or rather the one future that sets the value, we will see the main-thread printing out "Hello World!" because it will wait for the future to finish.

Now you just have to apply this fix in your code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM