Interview replay
Full round replay — thread pools
Timed verbal replay with pass/fail criteria per follow-up.
How to run this
The opener
“How do you size a thread pool, and what does an unbounded queue cost you?”
Budget: 45 seconds. Going long here is itself a fail signal.
Follow-ups
1. “In what order does ThreadPoolExecutor use core, max and the queue?”
Testing: The second step is where nearly everyone is wrong.
Scoring
Pass: Core threads, then QUEUE, then grow to maximumPoolSize once the queue is full, then reject. Notes that with an unbounded queue the last two steps are unreachable.
Fail: 'It creates a new thread when all threads are busy' — the common and wrong model.
2. “So what is wrong with Executors.newFixedThreadPool?”
Testing: Do they connect the ordering to the factory method?
Scoring
Pass: Its LinkedBlockingQueue holds Integer.MAX_VALUE, so it can never reject and never grows past core. Under sustained overload it accumulates tasks until the heap is gone.
Fail: 'Nothing, it's the standard one.'
3. “Someone wants to raise maximumPoolSize to fix a pool stuck at its core size. React.”
Testing: Can they apply the rule rather than recite it?
Scoring
Pass: It will do nothing until the queue is bounded, because threads beyond core are only created when the queue fills. Bound the queue first; then the maximum starts meaning something.
Fail: Agrees, or says 'try it and see'.
4. “Difference between submit() and execute()?”
Testing: The silent-failure half.
Scoring
Pass: submit() wraps the task in a FutureTask which catches everything and stores it in the Future — so a fire-and-forget task that throws is completely silent. execute() lets it reach the uncaught-exception handler.
Fail: 'submit returns a Future' and stops there.
5. “When would you choose CallerRunsPolicy?”
Testing: Backpressure as a concept.
Scoring
Pass: When I want the producer throttled rather than failed: the submitting thread runs the task, so it cannot outrun the pool. Bad choice when the caller must not block — an event loop or scheduler thread.
Fail: No opinion, or thinks it silently drops work.
6. “How do you size it for an endpoint calling two services and a database?”
Testing: Does the answer end at the formula, or at the downstream limit?
Scoring
Pass: Measure wait vs compute, but find the narrowest downstream limit first — more threads than the DB connection pool just moves the queue somewhere less visible. Alert on queue depth.
Fail: Quotes cores × (1 + wait/compute) with no way to obtain either number.
7. “Do virtual threads make pool sizing obsolete?”
Testing: Java 21 awareness plus judgement.
Scoring
Pass: For blocking I/O largely yes — a thread per task, no size to pick. Not for CPU-bound work, where the ceiling was always the CPU. And admission still has to be bounded somewhere or the unbounded queue has just moved.
Fail: 'Yes, virtual threads solve concurrency.'
Score yourself
← Back to How do you size a thread pool, and what does an unbounded queue cost you?