Suppose I have the following code:
CompletableFuture future
= CompletableFuture.supplyAsync( () -> 0);
thenAp
The difference has to do with the Executor
that is responsible for running the code. Each operator on CompletableFuture
generally has 3 versions.
thenApply(fn)
- runs fn
on a thread defined by the CompleteableFuture
on which it is called, so you generally cannot know where this will be executed. It might immediately execute if the result is already available.thenApplyAsync(fn)
- runs fn
on a environment-defined executor regardless of circumstances. For CompletableFuture
this will generally be ForkJoinPool.commonPool()
.thenApplyAsync(fn,exec)
- runs fn
on exec
.In the end the result is the same, but the scheduling behavior depends on the choice of method.