Card 06/ 09
All 9 cards
ComparisonDifficulty: Advanced1 min
Future Against CompletableFuture
A Future gives you one thing: a way to wait for a result. That is enough until you want to do something with the result without a thread standing there waiting for it.
| Compared on | Future | CompletableFuture |
|---|---|---|
| Get the result | get(), which blocks | join(), or a callback that does not |
| Do something when it arrives | Nothing — you must wait | thenApply, thenAccept, thenCompose |
| Combine two results | Wait for both in turn | thenCombine |
| Handle a failure | Catch around get() | exceptionally, handle |
| Complete it yourself | No | complete(value) |
CompletableFuture<Long> rows = CompletableFuture.supplyAsync(() -> countRowsIn(file), pool);
rows.thenApply(n -> n * 2)
.thenAccept(n -> log.info("{} rows", n))
.exceptionally(e -> { log.error("failed", e); return null; });Nothing blocks. Each stage says what to do when the previous one finishes, and the whole chain is a description that runs on the pool as results arrive — the same shape as a stream pipeline, over time instead of over elements.
The decision rule. A Future is enough when you submit a handful of tasks and wait for all of them. Reach for the composable one when a result feeds into another call, when two results have to be combined, or when there is no thread you can afford to block.