Backend Development 15 min read

Understanding Java Threads and Thread Pools

This article explains the concept of threads in Java, how to create them, the purpose and benefits of thread pools, the inheritance hierarchy of Java's Executor framework, key parameters of ThreadPoolExecutor, rejection policies, pool states, and the underlying working mechanism, supplemented with code examples.

政采云技术
政采云技术
政采云技术
Understanding Java Threads and Thread Pools

Thread is an execution flow within a process; a process can have multiple threads, sharing the process's resources.

Threads differ from processes in that each thread has its own entry point, execution sequence, and exit, but cannot run independently without the application.

In Java, a thread is an instance of java.lang.Thread .

Ways to create a thread in Java

Extend Thread and override run() .

Implement Runnable and override run() .

Implement Callable .

What is a thread pool and why use it?

A thread pool is a pool of reusable threads. Creating threads infinitely consumes resources and reduces stability; a thread pool manages threads centrally.

In concurrent environments, the system cannot know how many tasks to execute at any moment, leading to issues such as performance loss from frequent thread creation, risk of resource exhaustion, and instability.

Frequent creation and destruction cause performance overhead.

Unlimited thread creation may exhaust resources.

Uncontrolled thread creation/deletion can destabilize the system.

Thread pools address resource management, offering advantages:

Reduce resource consumption by reusing threads.

Improve response speed by avoiding thread creation latency.

Enhance manageability and stability by controlling thread count and preventing resource exhaustion.

Java thread pool inheritance diagram

Executor is the base interface defining execute(Runnable) . ExecutorService extends Executor adding submit() , shutdown() , invokeAll() , etc. AbstractExecutorService implements part of ExecutorService . ThreadPoolExecutor is the core implementation. ScheduledExecutorService extends ExecutorService for delayed execution, with ScheduledThreadPoolExecutor as its implementation.

public ThreadPoolExecutor(int corePoolSize,
  int maximumPoolSize,
  long keepAliveTime,
  TimeUnit unit,
  BlockingQueue<Runnable> workQueue,
  ThreadFactory threadFactory,
  RejectedExecutionHandler handler) {
    if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0)
        throw new IllegalArgumentException();
    if (workQueue == null || threadFactory == null || handler == null)
        throw new NullPointerException();
    this.acc = System.getSecurityManager() == null ? null : AccessController.getContext();
    this.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
}

Key parameters of ThreadPoolExecutor :

corePoolSize : number of core threads; tasks create new threads up to this number.

maximumPoolSize : maximum number of threads; when the queue is full, new threads are created up to this limit.

keepAliveTime : time that excess threads (beyond corePoolSize ) stay alive when idle.

unit : time unit for keepAliveTime .

workQueue : blocking queue holding tasks when core threads are busy.

threadFactory : factory to create new threads; default is Executors.DefaultThreadFactory .

rejectedExecutionHandler : policy for handling tasks when the pool cannot accept more.

Common rejection policies:

AbortPolicy – throws RejectedExecutionException .

CallerRunsPolicy – runs the task in the calling thread.

DiscardOldestPolicy – discards the oldest task in the queue and retries.

DiscardPolicy – silently discards the task.

Important thread pool attributes

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

ctl encodes the pool's run state (high 3 bits) and worker count (low 29 bits). The constants define the maximum worker count.

Thread pool states:

private static final int RUNNING    = -1 << COUNT_BITS;
private static final int SHUTDOWN   =  0 << COUNT_BITS;
private static final int STOP       =  1 << COUNT_BITS;
private static final int TIDYING    =  2 << COUNT_BITS;
private static final int TERMINATED =  3 << COUNT_BITS;

RUNNING – initial state, accepts new tasks.

SHUTDOWN – no new tasks, but existing tasks are processed.

STOP – no new tasks, ongoing tasks are interrupted.

TIDYING – all tasks completed, pool is terminating.

TERMINATED – pool has fully terminated.

Thread pool working principle

If current thread count < corePoolSize , a new thread is created for incoming tasks.

If thread count ≥ corePoolSize , tasks are queued in the BlockingQueue .

If the queue is full, new threads are created up to maximumPoolSize .

If creating a new thread would exceed maximumPoolSize , the task is rejected according to the rejection policy.

Learning summary

This article used threads as an entry point to explore Java's Executor hierarchy, clarified the meaning of all ThreadPoolExecutor parameters, introduced four rejection strategies, and explained the pool's state transitions and working mechanism, helping understand when and how to use thread pools effectively.

JavaconcurrencythreadpoolThreadExecutorThreadPoolExecutorRejectionPolicy
政采云技术
Written by

政采云技术

ZCY Technology Team (Zero), based in Hangzhou, is a growth-oriented team passionate about technology and craftsmanship. With around 500 members, we are building comprehensive engineering, project management, and talent development systems. We are committed to innovation and creating a cloud service ecosystem for government and enterprise procurement. We look forward to your joining us.

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.