CompletableFuture — Async Programming
Chain async operations with CompletableFuture: thenApply, thenCompose, allOf, and exception handling.
import java.util.concurrent.*;
import java.util.List;
import java.util.stream.Collectors;
public class AsyncDemo {
static ExecutorService executor = Executors.newFixedThreadPool(4);
static CompletableFuture<String> fetchUser(int id) {
return CompletableFuture.supplyAsync(() -> {
sleep(100); // simulate network call
return "User-" + id;
}, executor);
}
static CompletableFuture<List<String>> fetchOrders(String user) {
return CompletableFuture.supplyAsync(() -> {
sleep(100);
return List.of(user + "-Order1", user + "-Order2");
}, executor);
}
public static void main(String[] args) throws Exception {
// Chain: fetch user then orders
CompletableFuture<List<String>> result = fetchUser(1)
.thenCompose(user -> fetchOrders(user));
System.out.println(result.get()); // [User-1-Order1, User-1-Order2]
// Transform result
CompletableFuture<String> upper = fetchUser(2)
.thenApply(String::toUpperCase);
// Combine two futures
CompletableFuture<String> combined = fetchUser(1)
.thenCombine(fetchUser(2), (u1, u2) -> u1 + " & " + u2);
System.out.println(combined.get());
// Run all in parallel
List<CompletableFuture<String>> futures = List.of(
fetchUser(1), fetchUser(2), fetchUser(3)
);
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
List<String> users = futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList());
System.out.println(users);
// Error handling
fetchUser(-1)
.thenApply(String::toUpperCase)
.exceptionally(ex -> "Fallback: " + ex.getMessage())
.thenAccept(System.out::println);
executor.shutdown();
}
static void sleep(long ms) {
try { Thread.sleep(ms); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
}
}Use Cases
- Parallel API calls to multiple services
- Non-blocking data processing pipelines
- Combining results from independent async tasks
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
CompletableFuture Combinators — allOf, anyOf, compose
Compose async operations with CompletableFuture: allOf, anyOf, thenCombine, handle, and timeout.
Best for: Aggregating results from multiple microservices
Virtual Threads — Lightweight Concurrency
Use Java 21 virtual threads for massive concurrency without thread pool tuning or reactive frameworks.
Best for: High-concurrency web servers handling thousands of requests
ExecutorService — Thread Pool Management
Create and manage thread pools with ExecutorService: fixed, cached, scheduled, and custom pools.
Best for: Managing concurrent task execution
Concurrent Collections — Thread-Safe Maps
Use ConcurrentHashMap, CopyOnWriteArrayList, and BlockingQueue for thread-safe data structures.
Best for: Thread-safe caching in multi-threaded applications