Question 10 Β· Section 19

What does anyOf() method do and when is it useful

Structured Java interview answer with junior, middle, and senior-level explanation.

Language versions: English Russian Ukrainian

🟒 Junior Level

anyOf() β€” waits for the FIRST of the passed CompletableFutures to complete and returns its result.

CompletableFuture<String> fast = CompletableFuture.supplyAsync(() -> {
    Thread.sleep(100);
    return "Fast";
});

CompletableFuture<String> slow = CompletableFuture.supplyAsync(() -> {
    Thread.sleep(1000);
    return "Slow";
});

// Returns the result of the FIRST completed one
CompletableFuture<Object> any = CompletableFuture.anyOf(fast, slow);

any.thenAccept(result -> System.out.println(result));  // "Fast"

When to use:

  • Query multiple sources β€” whoever responds first
  • Fallback: primary and backup services
  • Timeout via an alternative CF

🟑 Middle Level

How it works

// Query multiple servers
CompletableFuture<String> server1 = queryServerAsync("server1");
CompletableFuture<String> server2 = queryServerAsync("server2");
CompletableFuture<String> server3 = queryServerAsync("server3");

// Take the first response
CompletableFuture<Object> fastest = CompletableFuture.anyOf(server1, server2, server3);

fastest.thenAccept(response -> System.out.println("Got response: " + response));

Important: anyOf() returns CompletableFuture<Object> β€” you need to cast the type:

CompletableFuture.anyOf(cf1, cf2)
    .thenAccept(result -> {
        String str = (String) result;  // cast is needed!
        System.out.println(str);
    });

Typical mistakes

  1. Unknown which CF completed:
    CompletableFuture.anyOf(cf1, cf2).thenAccept(result -> {
     // result β€” Object, unclear which CF it came from
     // If types differ β€” need to check
     if (result instanceof String s) { }
     if (result instanceof Integer i) { }
    });
    
  2. Remaining CFs continue executing:
    // anyOf does not cancel the remaining CFs!
    CompletableFuture.anyOf(fast, slow);
    // slow continues running in the background
    

πŸ”΄ Senior Level

Internal Implementation

public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs) {
    return new OrRelay<>(cfs, null);
}

// When the first CF completes β€” the result is copied into OrRelay
// The remaining CFs are ignored (but continue executing)

Architectural Trade-offs

anyOf() allOf()
First completed All completed
Object result Void result
Fast fail Full wait

Edge Cases

1. Timeout pattern:

CompletableFuture<String> operation = fetchDataAsync();
CompletableFuture<Object> timeout = CompletableFuture
    .delayedExecutor(5, TimeUnit.SECONDS)
    .thenApply(v -> { throw new TimeoutException(); });

CompletableFuture<Object> result = CompletableFuture.anyOf(operation, timeout);

2. Multiple sources with fallback:

CompletableFuture<Data> primary = fetchFromPrimaryAsync();
CompletableFuture<Data> fallback = fetchFromCacheAsync();

CompletableFuture<Object> any = CompletableFuture.anyOf(primary, fallback);

any.thenAccept(result -> {
    Data data = (Data) result;
    // anyOf may have completed from fallback while primary is still running.
    // isCompletedExceptionally() doesn't tell you WHO won the race.
    // Reliable approach β€” compare result with known sources.
    if (result == fallbackResult) {
        log.warn("Primary failed or hasn't completed yet, using fallback");
    }
});

3. Cancellation of remaining:

CompletableFuture<String> cf1 = fetchAsync(1);
CompletableFuture<String> cf2 = fetchAsync(2);
CompletableFuture<String> cf3 = fetchAsync(3);

CompletableFuture<Object> any = CompletableFuture.anyOf(cf1, cf2, cf3);

any.thenAccept(result -> {
    // Cancel the rest
    // cancel on an already completed CF is a no-op. But this code is misleading,
    // as if all three are still running. Better to track the winner.
    cf1.cancel(false);
    cf2.cancel(false);
    cf3.cancel(false);
});

Performance

anyOf():
- Creation: ~10 ns
- Overhead: ~5 ns per CF
- First completed β€” result

Cancellation of remaining CFs:
- cancel(false): ~100 ns
- But execution may continue

Production Experience

Resilient service call:

@Service
public class ResilientService {
    public CompletableFuture<String> getData(String key) {
        CompletableFuture<String> primary = primaryClient.getAsync(key);
        CompletableFuture<String> secondary = secondaryClient.getAsync(key);
        CompletableFuture<String> cache = cacheClient.getAsync(key);

        return CompletableFuture.anyOf(primary, secondary, cache)
            .thenApply(result -> (String) result);
    }
}

When NOT to use anyOf

  • Need ALL results β€” use allOf
  • Fastest may come from an unreliable source β€” anyOf returns the first, not the best

Best Practices

// βœ… anyOf for fastest response
CompletableFuture.anyOf(cf1, cf2, cf3)
    .thenAccept(result -> process((Type) result));

// βœ… Timeout via anyOf
CompletableFuture.anyOf(operation, timeoutCF);

// βœ… Cancel the rest on completion
any.thenAccept(r -> { cf1.cancel(false); cf2.cancel(false); });

// ❌ anyOf when you need all results
// ❌ Ignoring Object return type
// ❌ Not cancelling remaining CFs

🎯 Interview Cheat Sheet

Must know:

  • anyOf() returns the result of the FIRST completed CF
  • Returns CompletableFuture β€” cast is needed
  • Does not cancel remaining CFs β€” they continue executing
  • Latency = min(all CFs) β€” fastest response
  • Use case: fastest of multiple servers, fallback, timeout

Frequent follow-up questions:

  • Does anyOf cancel remaining CFs? β€” No, need manual cancel(false)
  • How to know which CF won? β€” Compare result with known sources
  • anyOf vs applyToEither? β€” applyToEither for two CFs (typed), anyOf for N (Object)
  • What if the first CF fails? β€” anyOf completes with an error. Need error handling

Red flags (DO NOT say):

  • β€œanyOf returns a typed result” β€” returns Object, cast is needed
  • β€œanyOf automatically cancels the rest” β€” no, they continue executing
  • β€œanyOf guarantees the best result” β€” only fastest, not best

Related topics:

  • [[9. What does allOf() method do and when to use it]]
  • [[8. How to combine results of multiple CompletableFutures]]
  • [[20. How to implement timeout for CompletableFuture]]
  • [[16. How to properly execute multiple parallel requests to microservices]]