Careeroza
Real World Example
Travel Search Aggregator (MakeMyTrip style)
A flight search page queries several airlines at once, waits at most a fixed time, ignores airlines that fail or time out, and shows the cheapest fares. This is a classic CompletableFuture fan-out / fan-in.
Example
import java.util.*;
import java.util.concurrent.*;
public class Main {
record Fare(String airline, int price) {}
static Fare query(String airline, int delayMs, int price) {
try { Thread.sleep(delayMs); } catch (InterruptedException e) { throw new RuntimeException(e); }
if (price < 0) throw new IllegalStateException(airline + " API error");
return new Fare(airline, price);
}
public static void main(String[] args) {
try (ExecutorService io = Executors.newFixedThreadPool(5)) {
Map<String, CompletableFuture<Optional<Fare>>> calls = new LinkedHashMap<>();
calls.put("IndiGo", call(io, "IndiGo", 100, 4899));
calls.put("Air India", call(io, "Air India", 150, 5600));
calls.put("Akasa", call(io, "Akasa", 80, 4650));
calls.put("SpiceJet", call(io, "SpiceJet", 50, -1)); // fails
calls.put("Vistara", call(io, "Vistara", 3000, 4300)); // too slow
CompletableFuture.allOf(calls.values().toArray(new CompletableFuture[0])).join();
calls.forEach((name, f) -> System.out.println(name + ": " +
f.join().map(fare -> "Rs " + fare.price()).orElse("unavailable")));
List<Fare> sorted = calls.values().stream().map(CompletableFuture::join)
.flatMap(Optional::stream).sorted(Comparator.comparingInt(Fare::price)).toList();
System.out.println("Cheapest: " + sorted.get(0));
}
}
static CompletableFuture<Optional<Fare>> call(ExecutorService io, String airline, int delay, int price) {
return CompletableFuture.supplyAsync(() -> Optional.of(query(airline, delay, price)), io)
.completeOnTimeout(Optional.empty(), 500, TimeUnit.MILLISECONDS)
.exceptionally(ex -> Optional.empty());
}
}Output
IndiGo: Rs 4899 Air India: Rs 5600 Akasa: Rs 4650 SpiceJet: unavailable Vistara: unavailable Cheapest: Fare[airline=Akasa, price=4650]
Production Notes
- Use a dedicated, bounded executor per downstream system so one slow airline cannot eat all threads (bulkhead pattern).
- Log failures inside
exceptionally; return a fallback instead of failing the whole page. - In Java 21 a virtual-thread executor makes this simpler: write blocking calls, run thousands at once.