×

java · level 3 · unit 6 · lesson 4

  1. meet it
  2. guess first
  3. your turn
  4. fix it
  5. nailed it

Tap a green word if you get lost.

meet it

Run jobs side by side, then combine them, or recover.

Two independent jobs, like loading a price and a delivery fee, should run at the same time. waits for both and adds them. For more, finishes when every one has.

Background jobs fail too. When a step throws, every later step is skipped, and join throws with the real error inside. Add and a failure turns into a sensible answer instead.

Put exceptionally where a fallback makes sense: late enough to catch the failures you expect, early enough that later steps still get a value.

import java.util.Map;
import java.util.concurrent.CompletableFuture;
public class Main {
    static int priceOf(String item) {
        Map<String, Integer> prices = Map.of("lamp", 2500, "desk", 12000);
        if (!prices.containsKey(item)) {
            throw new IllegalArgumentException("Unknown item: " + item);
        }
        return prices.get(item);
    }
    public static void main(String[] args) {
        CompletableFuture<Integer> lamp = CompletableFuture.supplyAsync(() -> priceOf("lamp"));
        CompletableFuture<Integer> delivery = CompletableFuture.supplyAsync(() -> 499);
        System.out.println("Lamp delivered: " + lamp.thenCombine(delivery, (p, d) -> p + d).join());
        CompletableFuture<Integer> desk = CompletableFuture.supplyAsync(() -> priceOf("desk"));
        CompletableFuture<Integer> rug = CompletableFuture.supplyAsync(() -> priceOf("rug"))
            .exceptionally(error -> 0);
        CompletableFuture.allOf(desk, rug).join();
        System.out.println("Desk: " + desk.join() + ", rug: " + rug.join());
    }
}

Prices here are in pence, so 2999 means 29.99.