multi threading
advanced

CompletableFuture

Compose asynchronous computations into pipelines — like Promises in JavaScript — without blocking on every step.

A plain Future can represent a result that isn't ready yet, but it is awkward: the only way to get the value is to block on get(), and you cannot chain "when this finishes, do that next" or combine several futures without manual coordination. CompletableFuture fixes this by making asynchronous results composable — you describe a pipeline of dependent steps, and each step runs when its input completes, without any thread blocking in between.

Pizza ordering app — track each pizza's status independently. "When all three are ready, send the delivery driver." No staring at a single oven.

Key Concepts

1
You start one with supplyAsync (for a value) or runAsync (for a side effect), which run on the common ForkJoinPool unless you pass your own executor. You then attach continuations: thenApply transforms the result, thenCompose chains another future (flattening, like flatMap), thenCombine merges two independent futures, and thenAccept/thenRun consume it. Error handling is part of the pipeline too — exceptionally supplies a fallback, while handle and whenComplete see both the value and any exception. Because each stage fires on completion rather than by polling, you can fan out dozens of calls and join them with allOf without dedicating a thread to waiting.
supplyAsyncrunAsyncthenApplythenComposethenCombine
2
A few sharp edges recur in interviews. The *Async variants run the continuation on a pool, whereas the non-async forms may run it on whatever thread completed the previous stage — which matters for blocking work or thread affinity. Exceptions propagate down the chain wrapped in a CompletionException, so unwrap getCause() when inspecting them. And the default common pool is shared across the whole JVM and sized to the CPU count, so running blocking I/O on it can starve everything else — pass a dedicated executor for blocking tasks.
*AsyncCompletionExceptiongetCause()