Question 26 Β· Section 19

What does join() method do and how does it differ from get()

get() has a timeout version: get(5, TimeUnit.SECONDS). join() has NO timeout variant. In production code where you need a timeout, use get() or wrap join() via orTimeout().

Language versions: English Russian Ukrainian

🟒 Junior Level

join() and get() β€” both wait for CompletableFuture to complete and return the result.

Main difference:

  • get() β€” throws checked exceptions (InterruptedException, ExecutionException)
  • join() β€” throws unchecked (CompletionException)
CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> "Hello");

// get() β€” requires try-catch
try {
    String result = cf.get();  // throws checked exceptions
} catch (InterruptedException | ExecutionException e) {
    // handle
}

// join() β€” simpler
String result = cf.join();  // throws CompletionException (unchecked)

🟑 Middle Level

When to use which

get() β€” when you need checked exceptions:

try {
    String result = cf.get(5, TimeUnit.SECONDS);  // with timeout
} catch (TimeoutException e) {
    // timeout handling
} catch (InterruptedException e) {
    // interrupt handling
}

Critical practical difference

get() has a timeout version: get(5, TimeUnit.SECONDS). join() has NO timeout variant. In production code where you need a timeout, use get() or wrap join() via orTimeout().

join() β€” for chains and tests:

// In chains
CompletableFuture.allOf(cf1, cf2, cf3)
    .thenApply(v -> {
        String r1 = cf1.join();  // no try-catch needed
        String r2 = cf2.join();
        String r3 = cf3.join();
        return combine(r1, r2, r3);
    });

// In tests
@Test
void test() {
    String result = cf.join();  // simpler
    assertEquals("expected", result);
}

Typical mistakes

  1. join() without error handling: ```java // ❌ If CF fails β€” CompletionException String result = cf.join(); // may throw

// βœ… With handling cf.exceptionally(ex -> β€œfallback”) .join(); // safe


---

## πŸ”΄ Senior Level

### Internal Implementation

```java
// Simplified representation. Actual JDK methods may differ.
public T get() throws InterruptedException, ExecutionException {
    Object r = reportGet();
    if (r instanceof AltResult alt) {
        if (alt.ex != null) throw new ExecutionException((Throwable) alt.ex);
    }
    return (T) r;
}

public T join() {
    Object r = reportGet();
    if (r instanceof AltResult alt) {
        if (alt.ex != null) throw new CompletionException((Throwable) alt.ex);
    }
    return (T) r;
}

// The only difference is the exception type!

Performance

get(): ~100 ns (checked exception handling)
join(): ~100 ns (same internals)

Difference is negligible β€” choice is based on convenience

Best Practices

// βœ… join() in chains
cf.thenApply(v -> cf2.join());

// βœ… join() in tests
assertEquals("expected", cf.join());

// βœ… get(timeout) for production
cf.get(5, TimeUnit.SECONDS);

// ❌ join() without error handling
// ❌ get() without timeout in production

🎯 Interview Cheat Sheet

Must know:

  • join() β€” unchecked CompletionException, get() β€” checked InterruptedException + ExecutionException
  • join() has NO timeout, get(timeout, unit) HAS timeout
  • join() is preferred in chains and tests, get(timeout) for production
  • Internally identical β€” difference is only in exception type
  • Both block the thread until CF completes

Common follow-up questions:

  • join() or get() β€” when which? β€” join() in chains/tests, get(timeout) in production
  • Can join() throw TimeoutException? β€” No. Need orTimeout() before join()
  • CompletionException vs ExecutionException? β€” CompletionException (join) β€” unchecked, ExecutionException (get) β€” checked
  • Does join() after allOf() block? β€” No, if allOf() is completed. But join() without allOf() β€” blocks

Red flags (DO NOT say):

  • β€œjoin() is non-blocking” β€” it blocks until CF completes
  • β€œget() and join() are completely identical” β€” different exception types, get has timeout
  • β€œjoin() without timeout in production is OK” β€” infinite waiting on error

Related topics:

  • [[21. How to implement timeout for CompletableFuture]]
  • [[24. How to test code with CompletableFuture]]
  • [[6. How to handle exceptions in CompletableFuture chain]]
  • [[14. What is blocking code and how to distinguish it from non-blocking]]