Backend Development 11 min read

Understanding Java Thread Pools: Creation, Execution Flow, Advantages, and Common Implementations

This article introduces Java thread pools, explaining their purpose, creation using ThreadPoolExecutor, execution flow, advantages such as resource reuse and management, common blocking queues, rejection policies, and provides multiple code examples of various pool types and a comprehensive monitoring example.

Full-Stack Internet Architecture
Full-Stack Internet Architecture
Full-Stack Internet Architecture
Understanding Java Thread Pools: Creation, Execution Flow, Advantages, and Common Implementations

Thread pools are a pooling technique that reuses existing threads to reduce the overhead of creating and destroying threads, while providing statistics for management.

1. Thread Pool Example

package com.sample.core.multithread.pool;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class MyTask implements Runnable {
    private int id;
    public MyTask(int id) {
        this.id = id;
    }
    @Override
    public void run() {
        System.out.println("线程:" + Thread.currentThread().getName() + "。任务id:" + id + ",正在运行!");
    }
}
public class SimpleThreadPool {
    public static void main(String[] args) {
        // 创建一个固定大小为5的线程池
        ExecutorService executor = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 10; i++) {
            executor.execute(new MyTask(i));
        }
        executor.shutdown();
    }
}

Running the program shows threads pool-1-thread-1 to pool-1-thread-5 executing ten tasks, demonstrating thread reuse.

2. Advantages of Thread Pools

Reuse existing threads to lower creation/destruction cost.

Improve response speed by executing tasks immediately.

Effective management and monitoring of thread status.

3. Creation and Execution Flow

ThreadPoolExecutor is typically used; its constructor parameters are explained:

public ThreadPoolExecutor(int corePoolSize,
    int maximumPoolSize,
    long keepAliveTime,
    TimeUnit unit,
    BlockingQueue
workQueue,
    ThreadFactory threadFactory,
    RejectedExecutionHandler handler)

Key parameters:

corePoolSize : number of core threads that stay alive even when idle.

maximumPoolSize : maximum number of threads.

keepAliveTime : timeout for non‑core threads.

unit : time unit for keepAliveTime .

workQueue : task queue (e.g., LinkedBlockingQueue ).

threadFactory : optional factory for creating threads.

handler : optional rejection policy.

4. Common Blocking Queues

ArrayBlockingQueue – bounded array‑based FIFO queue.

LinkedBlockingQueue – linked‑list based, optionally bounded (default Integer.MAX_VALUE ).

DelayQueue – unbounded queue that releases elements only after their delay expires.

PriorityBlockingQueue – unbounded queue that orders elements by priority.

SynchronousQueue – zero‑capacity queue that blocks until another thread takes the element.

5. Rejection Policies

AbortPolicy – throws RejectedExecutionException . public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { throw new RejectedExecutionException("Task " + r.toString() + " rejected from " + e.toString()); }

DiscardPolicy – silently discards the task. public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { }

DiscardOldestPolicy – discards the oldest task in the queue then retries. public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) { e.getQueue().poll(); e.execute(r); } }

CallerRunsPolicy – the submitting thread runs the task. public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) { r.run(); } }

6. Common Thread Pool Types

SingleThreadExecutor – one thread, core and max size = 1, uses an unbounded LinkedBlockingQueue . public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService( new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue ())); }

FixedThreadPool – fixed size, core = max, uses an unbounded LinkedBlockingQueue . public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue (), threadFactory); }

CachedThreadPool – creates new threads as needed, reuses idle ones, uses SynchronousQueue . public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue ()); }

ScheduledThreadPool – supports delayed and periodic tasks; max size = Integer.MAX_VALUE . public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue()); }

7. Comprehensive Example

A custom rejection handler is defined, a ThreadPoolExecutor is created with core size 1, max size 2, a 5‑element ArrayBlockingQueue , and the custom handler. Ten tasks are submitted, each prints its thread ID, sleeps for 300 ms, and prints completion. After each submission, pool statistics (core size, max size, current pool size, active threads, total tasks, queued tasks) are printed for monitoring.

package com.sample.core.multithread.pool;

import java.util.concurrent.*;
public class ThreadPoolExample {
    public static void main(String[] args) throws Exception {
        // Custom rejection policy
        RejectedExecutionHandler myHandler = (r, executor) -> {
            String msg = "这是自定义的拒绝策略";
            System.out.println(msg);
        };
        // Custom thread pool
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1, 2,
                500L, TimeUnit.MICROSECONDS, new ArrayBlockingQueue<>(5),
                Executors.defaultThreadFactory(), myHandler);
        for (int i = 0; i < 10; i++) {
            threadPool.submit(() -> {
                try {
                    System.out.println("线程id:"+Thread.currentThread().getId()+",开始运行");
                    Thread.sleep(300);
                    System.out.println("线程id:"+Thread.currentThread().getId()+",运行结束");
                } catch (Exception e) {
                    // handle
                }
            });
            // Monitor pool state
            System.out.println("当前核心线程数:"+ threadPool.getCorePoolSize() +
                ",最大线程数:" + threadPool.getMaximumPoolSize() +
                ",当前线程池大小:" + threadPool.getPoolSize() +
                ", 活动线程数:" + threadPool.getActiveCount() +
                ", 收到任务:" + threadPool.getTaskCount() +
                ", 等待任务数:" + threadPool.getQueue().size());
        }
        threadPool.shutdown();
    }
}

The article concludes that mastering thread pools is essential for Java development and interview preparation.

JavaConcurrencythreadpoolExecutorServiceRejectionPolicyBlockingQueue
Full-Stack Internet Architecture
Written by

Full-Stack Internet Architecture

Introducing full-stack Internet architecture technologies centered on Java

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.