Thread pool
π§΅ Thread Pools in Java¶
Imagine a kitchen with a fixed number of chefs π³ Orders (tasks) keep coming, but instead of hiring a new chef each time, you reuse the same team. Thatβs a thread pool.
π§ What is a Thread Pool?¶
A thread pool is a collection of pre-created threads that execute tasks from a queue.
π Managed via ExecutorService and ThreadPoolExecutor
```java id="2m6t8p" ExecutorService pool = Executors.newFixedThreadPool(3);
- You submit tasks
- Tasks go into a queue
- Threads pick tasks and execute
- Threads are reused
βοΈ Basic Example¶
```java id="ex1" ExecutorService pool = Executors.newFixedThreadPool(2);
for (int i = 1; i <= 5; i++) { int task = i; pool.submit(() -> { System.out.println("Task " + task + " by " + Thread.currentThread().getName()); }); }
pool.shutdown();
---
## ποΈ Types of Thread Pools
### 1. Fixed Thread Pool
```java id="tp1"
Executors.newFixedThreadPool(3);
- Fixed number of threads
- Extra tasks wait in queue
π Best for: controlled load
2. Cached Thread Pool¶
```java id="tp2" Executors.newCachedThreadPool();
* Creates threads as needed
* Reuses idle threads
* Can grow large β οΈ
π Best for: **short-lived tasks**
---
### 3. Single Thread Executor
```java id="tp3"
Executors.newSingleThreadExecutor();
- Only one thread
- Tasks executed sequentially
π Best for: ordered execution
4. Scheduled Thread Pool¶
```java id="tp4" Executors.newScheduledThreadPool(2);
* Runs tasks after delay or periodically
π Example:
```java id="tp5"
scheduler.schedule(() -> System.out.println("Run"), 2, TimeUnit.SECONDS);
π§ Core Components (under the hood)¶
ThreadPoolExecutor uses:
- Core Pool Size β minimum threads
- Max Pool Size β max threads
- BlockingQueue β holds tasks
- RejectedExecutionHandler β handles overflow
```java id="tp6" new ThreadPoolExecutor( 2, 4, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>() );
---
## π§ Rejection Policies
When queue is full:
* `AbortPolicy` β throws exception
* `CallerRunsPolicy` β caller thread runs task
* `DiscardPolicy` β silently drops
* `DiscardOldestPolicy` β removes oldest task
---
## βοΈ Why Thread Pool?
| Problem | Without Pool | With Pool |
|----------------------|--------------|------------|
| Thread creation cost | High | Low |
| Resource usage | Uncontrolled | Controlled |
| Performance | Poor | Better |
| Scalability | Hard | Easy |
---
## π― Real Use Cases
* Web servers (handle requests)
* APIs / microservices
* Background jobs
* File processing
* Async tasks
---
## β οΈ Best Practices
* Always call:
```java id="tp7"
pool.shutdown();
- Avoid
newCachedThreadPool()in heavy systems - Prefer custom
ThreadPoolExecutorfor control
π§ Interview Nuggets¶
- Thread pool uses BlockingQueue internally
- Threads are reused, not created every time
- Prevents OutOfMemoryError (too many threads)
π§ Memory Trick¶
Thread Pool = Reusable threads + Task queue π§΅β‘οΈπ¦
π§΅ Creation of Thread Pools (Deep Dive)¶
Think of a thread pool as a factory floor π You decide:
- how many workers (threads)
- how many jobs can wait (queue)
- what happens when factory is overloaded
That factory is built using ThreadPoolExecutor.
π§ 1. High-Level Creation (Easy Way)¶
Using Executors
π This hides complexity
π Internally uses ThreadPoolExecutor
πΉ Common factory methods¶
Executors.newFixedThreadPool(n);
Executors.newCachedThreadPool();
Executors.newSingleThreadExecutor();
Executors.newScheduledThreadPool(n);
π Good for quick usage π Not ideal for production (less control)
βοΈ 2. Real Creation (ThreadPoolExecutor)¶
This is where interviews live π₯
ThreadPoolExecutor pool = new ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepAliveTime,
TimeUnit.SECONDS,
workQueue,
threadFactory,
rejectionHandler
);
π§© Components Explained¶
1. π§΅ corePoolSize¶
π Minimum threads always alive
- Even if idle β threads stay
2. π maximumPoolSize¶
π Max threads allowed
- Used when queue is full
3. β±οΈ keepAliveTime¶
π Idle thread survival time
- Extra threads die after this
4. π¦ workQueue (VERY IMPORTANT)¶
π Where tasks wait
Types:
LinkedBlockingQueueβ unboundedArrayBlockingQueueβ fixed sizeSynchronousQueueβ no storage
5. π ThreadFactory¶
π Controls thread creation
Used for:
- Naming threads
- Setting priority
6. π§ RejectedExecutionHandler¶
π What happens when pool is full
Options:
AbortPolicyβ throws exceptionCallerRunsPolicyβ caller runs taskDiscardPolicyβ drops taskDiscardOldestPolicyβ removes oldest
π How ThreadPoolExecutor Works¶
This is the core algorithm π§
1. If threads < corePoolSize β create thread
2. Else β put task in queue
3. If queue full β create thread (until maxPoolSize)
4. If still full β reject task
π§ͺ Example (Full Control)¶
ThreadPoolExecutor pool = new ThreadPoolExecutor(
2, // core
4, // max
60, TimeUnit.SECONDS, // keep alive
new ArrayBlockingQueue<>(2) // queue
);
for (int i = 1; i <= 10; i++) {
int task = i;
pool.execute(() -> {
System.out.println("Task " + task +
" by " + Thread.currentThread().getName());
});
}
π― Behavior of Above Example¶
- First 2 tasks β new threads
- Next 2 β queue
- Next 2 β new threads (max reached)
- Remaining β β rejected
β οΈ Why NOT use Executors in production?¶
Example:
π Uses unbounded queue
Risk:
- Memory grows
- Possible crash π₯
π§ Best Practice¶
Always define:
π Controlled + predictable
π₯ Real Production Example¶
int cores = Runtime.getRuntime().availableProcessors();
ThreadPoolExecutor pool = new ThreadPoolExecutor(
cores,
cores * 2,
60,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
βοΈ Summary¶
| Component | Purpose |
|---|---|
| corePoolSize | base threads |
| maxPoolSize | limit threads |
| queue | task waiting |
| keepAlive | idle cleanup |
| rejection | overload handling |
π§ Memory Trick¶
ThreadPool = Threads + Queue + Rules π§΅π¦βοΈ