CompletableFuture composes asynchronous work

thenCombine joins two independent results, and join waits without a checked exception - the readable way to run calls in parallel and merge them.

Code
CompletableFuture<Integer> price = CompletableFuture.supplyAsync(() -> {
    try { Thread.sleep(20); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
    return 100;
});
CompletableFuture<Integer> tax = CompletableFuture.supplyAsync(() -> 18);

CompletableFuture<String> total = price.thenCombine(tax, (p, t) -> "total = " + (p + t));
System.out.println(total.join());

var chained = CompletableFuture.supplyAsync(() -> "jch")
        .thenApply(String::toUpperCase)
        .thenApply(s -> s + " ready");
System.out.println(chained.join());
Output
total = 118
JCH ready
Advertisement

Run this yourself in the Online Java Compiler, spin up a live REST API in the API Sandbox, or practise with Java interview questions.

Published 2026-07-30