DEV Community

Code Green
Code Green

Posted on

explain thread pool in java

Thread Pool in Java

A thread pool is a collection of pre-created worker threads that execute submitted tasks, reusing threads to avoid the overhead of creating and destroying threads for each task. Java provides built-in thread-pool support in the java.util.concurrent package.

Key benefits

  • Reduced latency: avoid thread creation cost for each task.
  • Controlled concurrency: limit number of concurrent threads to match resources.
  • Resource management: prevents thread explosion that can exhaust memory/CPU.
  • Task queuing: tasks wait in a queue when all threads are busy.

Core concepts

  • Worker threads: threads that repeatedly take tasks from a queue and run them.
  • Task (Runnable/Callable): units of work submitted to the pool.
  • Task queue: holds waiting tasks (bounded or unbounded).
  • Pool size: number of active worker threads (core and maximum).
  • Keep-alive time: time non-core threads may remain idle before terminating.
  • RejectedExecutionHandler: policy for handling tasks when the queue is full and pool is at max.

Java APIs

  • Executors factory methods (java.util.concurrent.Executors):
    • Executors.newFixedThreadPool(n): fixed-size pool.
    • Executors.newCachedThreadPool(): dynamic pool that creates threads as needed and reuses idle ones.
    • Executors.newSingleThreadExecutor(): single-worker pool.
    • Executors.newScheduledThreadPool(n): for delayed/periodic tasks.
  • Core classes/interfaces:
    • Executor: single-method execute(Runnable).
    • ExecutorService: extends Executor; supports lifecycle (submit, shutdown, awaitTermination).
    • ScheduledExecutorService: supports scheduling tasks.
    • ThreadPoolExecutor: configurable concrete implementation.
    • Future / FutureTask: represent task results and allow cancellation.

Typical ThreadPoolExecutor constructor parameters

  • corePoolSize — minimum number of threads to keep.
  • maximumPoolSize — maximum allowed threads.
  • keepAliveTime & unit — idle time before reclaiming extra threads.
  • workQueue — queue implementation (e.g., LinkedBlockingQueue, ArrayBlockingQueue, SynchronousQueue).
  • threadFactory — creates new threads.
  • handler — RejectedExecutionHandler when saturated (AbortPolicy, CallerRunsPolicy, DiscardPolicy, DiscardOldestPolicy).

Example: fixed thread pool

ExecutorService pool = Executors.newFixedThreadPool(4);
for (int i = 0; i < 10; i++) {
    final int id = i;
    pool.submit(() -> {
        System.out.println("Task " + id + " running in " + Thread.currentThread().getName());
        try { Thread.sleep(500); } catch (InterruptedException ignored) {}
    });
}
pool.shutdown();
Enter fullscreen mode Exit fullscreen mode

Best practices

  1. Prefer Executors factory methods for common use-cases; use ThreadPoolExecutor for fine control.
  2. Choose queue type based on desired behavior: bounded queue for backpressure, SynchronousQueue for direct handoff.
  3. Set sensible pool sizes: typically related to number of CPU cores (IO-bound vs CPU-bound tasks differ).
  4. Always shut down ExecutorService (shutdown or shutdownNow) to allow JVM exit.
  5. Use Future to get results or cancel tasks; prefer CompletableFuture for composition.
  6. Avoid unbounded queues with unbounded task submission — can lead to OOM.

Top comments (0)