CompletableFuture and async composition question 94 of 180 senior
Which thread runs your callback if you use thenApply rather than thenApplyAsync?
- Always the common ForkJoinPool
- Correct: Whichever thread completed the previous stage, or the calling thread if it was already complete
- Always the thread that created the future
- A new thread each time
The non-async variants run on whatever thread happens to make the value available. If the previous stage is still running, the callback runs on the thread that completes it. If the future was already complete when you attached the callback, it runs immediately on your thread.
That means a chain of thenApply calls can execute on a Netty I/O thread, a client library's callback
thread, or the main thread, depending on timing. Put something slow or blocking there and you have
stalled someone else's event loop. This is the single most common CompletableFuture bug in
production.
The *Async variants take control back: with no executor argument they use the common
ForkJoinPool, which is also wrong for blocking work. Pass your own executor.
Quiz yourself on CompletableFuture and async composition Suggest a correction