Understanding Java ThreadPoolExecutor: Creation, Parameters, and Execution Flow
The article explains why multithreading is essential for modern CPUs, introduces thread pools to reduce overhead, and details Java's ThreadPoolExecutor creation parameters, execution process, and core methods such as addWorker, runWorker, and getTask, using JDK 1.8 source code examples.
As CPU core counts increase, multithreading becomes essential for fully utilizing computing power, making thread‑pool technology a must‑know for server‑side developers.
Creating and destroying threads incurs system calls and resource consumption, so thread pools are introduced to avoid frequent thread creation and destruction.
In Java, the Executors utility class creates a thread pool by instantiating a ThreadPoolExecutor object, a common interview topic; this article examines its source code to explain how ThreadPoolExecutor works.
1. Thread Pool Creation
Below is the most complete constructor of ThreadPoolExecutor:
corePoolSize: Number of core threads that stay alive even when there are no tasks.
maximumPoolSize: Maximum number of threads in the pool.
keepAliveTime: Time that excess idle threads wait before terminating.
unit: Time unit for keepAliveTime.
workQueue: Blocking queue that holds submitted tasks.
threadFactory: Factory that creates new threads, typically naming them.
handler: Rejection policy invoked when the pool is saturated.
These parameters are frequently asked in interviews.
2. Thread Pool Execution Process
The following diagram illustrates the execution flow of a thread pool.
When a task is submitted, the pool first checks if the current thread count is less than corePoolSize; if so, a new thread is created. Otherwise the task is placed into workQueue. If workQueue is full, the pool checks whether the thread count is below maximumPoolSize to possibly create another thread; if not, the rejection handler is invoked.
The following sections examine the JDK 1.8.0_111 source code.
1. executor method
Check if active thread count < corePoolSize; if true, call addWorker to create a thread.
If not, add the task to workQueue.
If adding to workQueue fails, attempt to create a thread; if that also fails (thread count ≥ maximumPoolSize), invoke reject (handler).
2. addWorker method
This code runs when creating a non‑core thread ( core = false). It checks whether the current thread count is ≥ maximumPoolSize; if so, it returns false, representing the failure case described earlier.
Create a Worker object, which also instantiates a Thread.
Start the thread.
3. Worker implementation
When a Worker is created, threadFactory creates a thread; the thread then executes the Worker's run method.
4. runWorker logic
runWorkerrepeatedly calls getTask to fetch tasks from the workQueue and executes them; as long as getTask does not return null, the thread continues running.
5. getTask implementation
If allowCoreThreadTimeOut is false and the current thread count > corePoolSize, the pool polls workQueue with a timeout of keepAliveTime; if the timeout expires, the loop exits and the thread terminates.
If the current thread count ≤ corePoolSize, the pool calls workQueue.take() and blocks waiting for tasks.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
