10

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);
}));
1
  • Did this not print following lines? end blocking Result: 42
    – TriCore
    Commented Nov 1, 2018 at 22:05

1 Answer 1

20

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?

Not the answer you're looking for? Browse other questions tagged or ask your own question.