CompletableFuture and async composition question 101 of 180 senior
When is CompletableFuture the wrong tool now that virtual threads exist?
- Never, async is always better
- Correct: When the only reason for it was to avoid blocking a pooled thread: on virtual threads, straight-line blocking code is cheaper to read and to debug
- When you have more than three stages
- When the tasks are CPU-bound
Async composition exists because blocking a platform thread is expensive. Virtual threads remove that
premise: a blocked virtual thread unmounts from its carrier and costs almost nothing, so plain
sequential code with plain try/catch, a readable stack trace and a debugger that works is once
again affordable.
CompletableFuture still earns its place for genuine fan-out and fan-in, for bridging callback-based
APIs, and for composing results that arrive from elsewhere. But "we used it so we would not block"
should now be re-examined, and structured concurrency covers the fan-out case with better
cancellation.
The nuanced answer to give: async is about the shape of the dependencies, not about the cost of a thread, and the cost of a thread was the only reason most codebases adopted it.
Quiz yourself on CompletableFuture and async composition Suggest a correction