Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CompletableFuture.thenAccept can indeed block

Unlike stated in some blogs(e.g. I can't emphasize this enough: thenAccept()/thenRun() methods do not block) CompletableFuture.thenAccept can indeed block. Consider the following code, uncommenting the pause method call will cause thenAccept to block:

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    log.trace("return 42");
    return "42";
});

//pause(1000); //uncommenting this will cause blocking of thenAccept

future.thenAccept((dbl -> {
    log.trace("blocking");
    pause(500);
    log.debug("Result: " + dbl);
}));

log.trace("end");
pause(1000);

Can we be sure that the following will not block? It's my understanding that if the supplyAsync runs immediately then the thenAccept could block, no?

CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
    return "42";
}).thenAccept((dbl -> {
    pause(500);
    log.debug("Result: " + dbl);
}));
like image 767
Roland Avatar asked May 12 '17 09:05

Roland


1 Answers

You are right, thenAccept() will block if the future is already completed. Also note that when it is not the case, it will cause the thread that completes it to block at the time of completion.

This is why you have thenAcceptAsync(), which will run your Consumer in a non-blocking way:

CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
    return "42";
}).thenAcceptAsync((dbl -> {
    pause(500);
    log.debug("Result: " + dbl);
}));

See also Which executor is used when composing Java CompletableFutures?

like image 111
Didier L Avatar answered Oct 27 '22 01:10

Didier L