Phase 19 of 20 · Topic 19.1

ExecutorService & ThreadPoolExecutor Tuning

1Concept

`ExecutorService` decouples task submission from execution thread pools. `ThreadPoolExecutor` parameters: 1. `corePoolSize` (baseline threads); 2. `maximumPoolSize` (burst cap); 3. `workQueue` (bounded `ArrayBlockingQueue` prevents OOM); 4. `RejectedExecutionHandler` (CallerRunsPolicy, AbortPolicy).

2Architecture Diagram

Task Submitted ---> [ corePoolSize full? ] --No--> Spawn new thread
                           |
                          Yes
                           v
                   [ workQueue full? ] --No--> Enqueue task
                           |
                          Yes
                           v
               [ maximumPoolSize reached? ] --No--> Spawn burst thread
                           |
                          Yes
                           v
             [ Trigger RejectedExecutionHandler ]

3Code Example

Core Java
import java.util.concurrent.*;

public class ExecutorTuningDemo {
    public static void main(String[] args) throws Exception {
        // Production-grade ThreadPoolExecutor configuration
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
            2,                          // corePoolSize
            4,                          // maximumPoolSize
            60L, TimeUnit.SECONDS,      // keepAliveTime
            new ArrayBlockingQueue<>(10),// Bounded Queue (prevents OOM)
            new ThreadPoolExecutor.CallerRunsPolicy() // Backpressure handler
        );

        for (int i = 1; i <= 4; i++) {
            final int taskId = i;
            executor.execute(() -> {
                System.out.println("Task " + taskId + " running on " + Thread.currentThread().getName());
            });
        }

        executor.shutdown();
        executor.awaitTermination(5, TimeUnit.SECONDS);
    }
}

4Expected Output

Task 1 running on pool-1-thread-1
Task 2 running on pool-1-thread-2
Task 3 running on pool-1-thread-1
Task 4 running on pool-1-thread-2

5Key Takeaways

  • NEVER use `Executors.newCachedThreadPool()` or `newFixedThreadPool()` without bounds in production; unbounded queues cause OutOfMemoryError.
  • `CallerRunsPolicy` provides graceful backpressure by throttling task submitters.
  • Always call `executor.shutdown()` and `awaitTermination()` during application graceful shutdown.