The common pool (ForkJoinPool.commonPool()) is a single, JVM-wide ForkJoinPool created lazily and shared by everything that doesn't supply its own pool: every parallel stream, CompletableFuture's default *Async methods, and any fork/join task submitted without a target pool. Its parallelism defaults to Runtime.availableProcessors() - 1 (the submitting thread counts as one worker).
Why "shared by everything" is the trap
Because there is exactly one common pool and it's sized for CPU-bound work (cores − 1 threads), any task that blocks — a JDBC call, an HTTP request, Thread.sleep, acquiring a contended lock — parks a worker without doing useful work. With only a handful of workers, a few blocked tasks can stall the entire pool. The damage isn't local: an unrelated parallel stream elsewhere in the app now has no threads to run on.
// DANGER: blocking I/O on the common pool starves every other parallel stream
List<Order> orders = ids.parallelStream()
.map(id -> httpClient.fetchOrder(id)) // blocks a common-pool worker
.toList();
The fixes
1. Run on your own pool. A dedicated ForkJoinPool (or ExecutorService) isolates the blocking work:
ForkJoinPool pool = new ForkJoinPool(32);
try {
List<Order> orders = pool.submit(() ->
ids.parallelStream().map(httpClient::fetchOrder).toList()
).get();
} finally {
pool.shutdown();
}
(Submitting a parallel stream from inside another ForkJoinPool makes it use that pool — a well-known, if slightly hacky, idiom.)
2. Use ManagedBlocker. If you must block inside a fork/join task, wrap it in a ForkJoinPool.ManagedBlocker. The pool detects the impending block and compensates by spinning up a temporary extra worker, preserving target parallelism.
ForkJoinPool.managedBlock(new ForkJoinPool.ManagedBlocker() {
public boolean block() throws InterruptedException { result = queue.take(); return true; }
public boolean isReleasable() { return result != null; }
});
3. For I/O-bound fan-out, prefer virtual threads (CompletableFuture with a virtual-thread executor, or StructuredTaskScope) over the common pool entirely.