Java CompletableFuture

Asynchronous programming with composable futures for non-blocking operations

java (8+) 2025-11-03 async concurrency futures java8

Description

CompletableFuture is a powerful class introduced in Java 8 for asynchronous programming. It represents a future result that can be completed asynchronously and provides methods for composing, combining, and handling asynchronous operations.

Key Features

  • Asynchronous execution: Run tasks without blocking the main thread
  • Composition: Chain multiple async operations together
  • Combination: Combine results from multiple futures
  • Exception handling: Handle errors in async operations
  • Thread pool control: Use custom ExecutorService

Common Patterns

  • thenApply: Transform result of one future
  • thenCompose: Chain futures sequentially
  • thenCombine: Combine two futures
  • allOf/anyOf: Wait for multiple futures
  • Exception handling: handle, exceptionally, whenComplete

Code

RAW
import java.util.concurrent.*;import java.util.function.*;import java.util.stream.Collectors;import java.util.List;public class AsyncUtils {        // Simple async execution    public static <T> CompletableFuture<T> supplyAsync(Supplier<T> supplier) {        return CompletableFuture.supplyAsync(supplier);    }        // Async execution with custom executor    public static <T> CompletableFuture<T> supplyAsync(Supplier<T> supplier, ExecutorService executor) {        return CompletableFuture.supplyAsync(supplier, executor);    }        // Transform result    public static <T, R> CompletableFuture<R> thenApply(CompletableFuture<T> future, Function<T, R> mapper) {        return future.thenApply(mapper);    }        // Chain futures    public static <T, R> CompletableFuture<R> thenCompose(CompletableFuture<T> future, Function<T, CompletableFuture<R>> mapper) {        return future.thenCompose(mapper);    }        // Combine two futures    public static <T, U, R> CompletableFuture<R> thenCombine(CompletableFuture<T> future1, CompletableFuture<U> future2, BiFunction<T, U, R> combiner) {        return future1.thenCombine(future2, combiner);    }        // Wait for all futures    public static CompletableFuture<Void> allOf(List<CompletableFuture<?>> futures) {        return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));    }        // Wait for any future    public static <T> CompletableFuture<Object> anyOf(List<CompletableFuture<T>> futures) {        return CompletableFuture.anyOf(futures.toArray(new CompletableFuture[0]));    }        // Handle exceptions    public static <T> CompletableFuture<T> handle(CompletableFuture<T> future, BiFunction<T, Throwable, T> handler) {        return future.handle(handler);    }}
RAW
// Simple async executionCompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {    try {        Thread.sleep(1000);        return "Hello";    } catch (InterruptedException e) {        throw new RuntimeException(e);    }});// Transform resultCompletableFuture<Integer> length = future.thenApply(String::length);// Chain operationsCompletableFuture<String> chained = future    .thenApply(s -> s + " World")    .thenApply(String::toUpperCase);// Combine two futuresCompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello");CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "World");CompletableFuture<String> combined = future1.thenCombine(    future2,    (s1, s2) -> s1 + " " + s2);// Wait for allList<CompletableFuture<String>> futures = Arrays.asList(    CompletableFuture.supplyAsync(() -> "Task 1"),    CompletableFuture.supplyAsync(() -> "Task 2"),    CompletableFuture.supplyAsync(() -> "Task 3"));CompletableFuture<Void> allDone = CompletableFuture.allOf(    futures.toArray(new CompletableFuture[0]));// Exception handlingCompletableFuture<String> safe = future    .exceptionally(ex -> "Error: " + ex.getMessage())    .handle((result, ex) -> {        if (ex != null) {            return "Handled: " + ex.getMessage();        }        return result;    });// Get result (blocking)try {    String result = future.get();    // or with timeout    String result2 = future.get(5, TimeUnit.SECONDS);} catch (Exception e) {    e.printStackTrace();}

Comments

No comments yet. Be the first to comment!