Thread Pool
A thread pool reuses a fixed set of worker threads to execute many tasks, bounding concurrency and avoiding per-task thread creation.
Definition
A thread pool maintains a set of pre-created worker threads that pull tasks from a queue. Instead of spawning a thread per task — costly in memory and scheduling — the pool caps the number of concurrent workers, queues excess work, and reuses threads across tasks. Its behaviour is governed by the pool size, the queue policy, and how new work is rejected when both are saturated.
Context and scope
The default execution model for server request handling, background jobs, and CPU-bound parallelism in nearly every runtime and application server.
Common misconceptions
- Bigger pools mean more throughput — beyond the bottleneck, extra threads only add context-switching and memory pressure
- Pool size equals core count always — CPU-bound work tracks cores, but I/O-bound work may need more threads to overlap waits
- A pool is a queue with no limits — the queue can grow unbounded and turn overload into a memory or latency failure
Anti-patterns
- Submitting tasks that block on each other inside the same small pool, so the pool deadlocks on its own work
- Using an unbounded queue that hides overload until latency explodes
- Sizing the pool without measuring the bottleneck resource, so threads contend instead of work
Related concepts
Related examples
Authoritative source
What it is
A thread pool creates a fixed or bounded number of worker threads at startup. Tasks arrive on a queue; idle workers take them, execute, and return for more. When all workers are busy, tasks wait, and when the queue also fills, the pool must reject, block, or apply backpressure. The pool thus converts an open-ended demand into a bounded, tunable supply of concurrency, and reuses threads whose creation cost would otherwise be paid per task.
Why it matters
Creating a thread per request wastes memory and CPU on scheduling, and unbounded concurrency lets a spike overwhelm the process. A pool bounds resource use, smooths bursts, and keeps the number of in-flight tasks aligned with what the machine can actually handle. It is the layer where overload policy is expressed: queue, shed, or slow down.
How to use it well
Size the pool to the bottleneck: roughly the core count for CPU-bound work, higher for I/O-bound work that spends time waiting, and validate by measurement rather than formula. Keep tasks independent so a worker never waits on another task in the same pool, and set a bounded queue with an explicit rejection or backpressure policy. Monitor queue depth and active workers, because a growing queue is the earliest sign of saturation.