CompletableFuture Composition
Implement or sketch code for CompletableFuture Composition. Explain the logic, complexity, and pros/cons of this approach.
Answers use simple, clear English.
Quick interview answer
Logic: supplyAsync runs async task; thenApply transforms; thenCompose flattens nested futures; allOf waits for batch. Exceptionally/handle for error paths.
Detailed answer
Logic: supplyAsync runs async task; thenApply transforms; thenCompose flattens nested futures; allOf waits for batch. Exceptionally/handle for error paths. Complexity notes included in code section when present. Pros: Composable async without raw callbacks; integrates with thread pools. Cons: Default ForkJoinPool.commonPool() shared — inject Executor for isolation. Core: supplyAsync runs async task; thenApply transforms; thenCompose flattens nested futures; allOf waits for batch. Exceptionally/handle for error paths. Real-time example: Aggregate microservice responses: CompletableFuture.allOf(userF, ordersF).thenApply(...). Pros: Composable async without raw callbacks; integrates with thread pools. Cons: Default ForkJoinPool.commonPool() shared — inject Executor for isolation. Common mistakes: Blocking get() on async chain in request thread; lost exceptions without handle. Best practices: Specify executor for IO; use orTimeout/join with timeout in Java 9+. Audience level: Junior.
Full explanation
supplyAsync runs async task; thenApply transforms; thenCompose flattens nested futures; allOf waits for batch. Exceptionally/handle for error paths.
Real example & use case
Aggregate microservice responses: CompletableFuture.allOf(userF, ordersF).thenApply(...).
Pros & cons
Pros: Composable async without raw callbacks; integrates with thread pools. Cons: Default ForkJoinPool.commonPool() shared — inject Executor for isolation.
Code example
CompletableFuture<String> user = CompletableFuture
.supplyAsync(() -> fetchUser())
.thenApply(u -> u.toUpperCase());
CompletableFuture<Integer> orders = CompletableFuture
.supplyAsync(() -> countOrders());
CompletableFuture<String> summary = user.thenCombine(orders,
(u, n) -> u + " has " + n + " orders");Practice code · java (view only · no execution)
CompletableFuture<String> user = CompletableFuture
.supplyAsync(() -> fetchUser())
.thenApply(u -> u.toUpperCase());
CompletableFuture<Integer> orders = CompletableFuture
.supplyAsync(() -> countOrders());
CompletableFuture<String> summary = user.thenCombine(orders,
(u, n) -> u + " has " + n + " orders");Common mistakes
Blocking get() on async chain in request thread; lost exceptions without handle.
Best practices
Specify executor for IO; use orTimeout/join with timeout in Java 9+.
Follow-up questions
Only answered follow-ups are shown — click to open with full answers