Thread Pool / Executor
When to Use Thread Pool / Executor
In Practice
ThreadPoolExecutor and ForkJoinPool (which backs CompletableFuture and parallel streams). Tomcat / Jetty / Netty all use fixed-size pools. Python's concurrent.futures.ThreadPoolExecutor.Sketch
Java
ExecutorService pool = new ThreadPoolExecutor(
16, 64, // core, max
60L, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(1000), // bounded queue
new ThreadPoolExecutor.CallerRunsPolicy()
);
Future<Result> f = pool.submit(() -> handle(req));How Thread Pool / Executor Comes Up in Interviews
Scenario
Your fixed-size executor of 16 threads is stuck. Threads are running tasks that submit subtasks to the same pool and wait on their results. Throughput drops to zero. What's the conceptual category of this bug?
Classic pool-induced deadlock: a task waits for a subtask that can't be scheduled because all pool threads are blocked waiting. Either split the pools (one per layer), use ForkJoinPool's managed blocker, or restructure with CompletableFuture.thenCompose so callers don't block worker threads.
Senior interview move: 'never block a worker thread waiting on a future scheduled by the same pool.' Reactive frameworks (Project Reactor, Vert.x) enforce this by making blocking an explicit ceremony.
Scenario
Your service ingests 50k HTTP requests/sec, each doing 5ms of CPU work. Spawning a thread per request blows the box; you want a fixed number of OS threads pulling work from a queue, with per-thread reuse.
A thread pool / executor is exactly 'N worker threads pulling tasks from a queue.' Futures/async help with I/O fan-out but you still need an executor underneath to actually run the work.