In programming, we usually create a thread directly when we need to use a thread, which is convenient to implement, but it also poses the same problem:
If a large number of concurrent threads are required, after each thread is created, a task with a short execution time ends the thread, which can greatly reduce the efficiency of the system, as the frequent creation and destruction of threads wastes a great deal of time and resources.
In Java, we can avoid this situation by using a thread pool. Below we will analyze the Java thread pool from the thread pool core class Threadpoolexecutor class. 1. Thread pool Threadpoolexecutor class 1.1 Threadpoolexecutor class construction method
The Java.util.concurrent.ThreadPoolExecutor class in Java is the core class of the thread pool, and here's a look at how to construct the Threadpoolexecutor class:
Public threadpoolexecutor (int corepoolsize, int maximumpoolsize, Long KeepAliveTime, timeunit unit, BLOCKINGQUEUE<RUNNABL E> workqueue) {This (corepoolsize, maximumpoolsize, KeepAliveTime, Unit, Workqueue, Executors.defa
Ultthreadfactory (), DefaultHandler);
Public threadpoolexecutor (int corepoolsize, int maximumpoolsize, Long KeepAliveTime, timeunit unit, Blockingqueue<runn Able> Workqueue, Threadfactory threadfactory) {This (corepoolsize, Maximumpoolsiz
E, KeepAliveTime, Unit, Workqueue, Threadfactory, DefaultHandler);
Public threadpoolexecutor (int corepoolsize, int maximumpoolsize, Long KeepalivetIME, timeunit Unit, blockingqueue<runnable> Workqueue, Rejectedexecutionhandler handler) {This (corepoolsize, Maximumpoolsize, KeepAliveTime
, unit, Workqueue, Executors.defaultthreadfactory (), handler);
Public threadpoolexecutor (int corepoolsize, int maximumpoolsize, Long KeepAliveTime, timeunit unit, blockingqueue< Runnable> Workqueue, Threadfactory threadfactory, Rejectede Xecutionhandler handler) {
As shown in the preceding code, the Threadpoolexecutor class provides 4 methods of construction, and in fact, by looking at the constructor method source code of the Threadpoolexecutor class, It can be learned that the first 3 constructors call the 4th constructor to complete the initialization of the threadpoolexecutor.
Let's take a detailed description of what each parameter in the constructor means:
int corepoolsize: The size of the core pool. After the thread pool has been created, there is no thread in the threads pools. Unless the Prestartallcorethreads () method or the Prestartcorethread () method is invoked, the name of the two methods can also be inferred, which is the meaning of the pre-created thread, That is, create a corepoolsize thread or a thread in the thread pool before the task arrives. By default, the number of threads in the newly created thread pool is 0.
When the thread pool is less than corepoolsize, each new task is committed, and a new thread is created by the thread pool, even if the other worker threads in the thread pool are idle.
When the number of threads in the thread pool is greater than corepoolsize and less than Maxmumpoolsize, the newly committed task is placed in the task queue, and a new thread is created only after the task queue is full.
The Getcorepoollsize () method enables you to get the core thread top values for the set of the thread pool. Typically, the corepoolsize is set up when the online pool is created, but it is also possible to dynamically adjust the number of core threads of the thread pool by calling the Setcorepoolsize method during the thread pool run.
int maximumpoolsize: The maximum number of threads for the thread pool. This parameter represents the maximum number of threads that the thread pool can create.
The Getmaximumpoolsize () method allows you to get the maximum number of threads set by the thread pool. Typically, the maximumpoolsize online pool is created, but the thread pool's maximum number of threads can also be dynamically adjusted by calling the Setmaximumpoolsize () method while the online pool is running.
Long KeepAliveTime: How long it will be terminated when a thread does not perform a task. If the current thread pool is larger than corepoolsize, the maximum amount of time that a thread exceeding the corepoolsize number can remain idle before terminating. This provides a means to reduce the waste of resources when the online pool is inactive. This parameter can also be dynamically adjusted by invoking the Setkeepalivetime method.
By default, this parameter only works if the thread pool has a number of threads larger than corepoolsize, and applies to excessive threads. However, you can also use the Allowcorethreadtimeout (Boolean) method to make the parameter equally applicable to the core thread.
Timeunit Unit: The time units of the parameter KeepAliveTime, there are 7 kinds of values, and the 7 static properties of the Timeunit class are as follows:
Timeunit.days; Days
timeunit.hours; Hour
timeunit.minutes; Minute
Timeunit.seconds; Second
timeunit.milliseconds; Millisecond
timeunit.microseconds; Delicate
timeunit.nanoseconds; Na sec
Blockingqueue<runnable> workqueue: Blocks queues to store tasks that will be waiting to be performed. Any blockingqueue can be used to store committed tasks.
Common three types of queues are as follows:
Synchronousqueue: The queue does not save the committed task, but instead creates a thread directly to perform the task, which usually requires that the thread pool's maximumpoolsize be unlimited. In other words, it is allowed to create threads indefinitely, even if the threads cannot get the CPU. This is appropriate for dealing with tasks that are interdependent, and avoids the creation of deadlocks because it is possible to quickly execute and release some resources.
Linkedblockingqueue: Advanced first Out queue based on the list. If you do not specify the size of the queue when you create the queue, the queue size defaults to Integer.max_value. This means that the team is listed as an infinite queue, and when the number of core threads is working, it will cause the newly committed task to wait for a long time in the queue. No new threads will be created because the queue is too long to be filled, and in another respect the Maximumpoolsize parameter does not work. The queue queues are independent of each other for tasks, such as Web service requests.
Arrayblockingqueue: An advanced first out queue based on an array. Creating the queue must specify the size of the queue, that is, the queue is bounded. There needs to be a trade-off between maximunpoolsize and Queuesize.
Threadfactory threadfactory: A thread factory used to create a new thread. If you do not specify a thread factory, the default thread factory Excutors.defaultthreadfactory is used.
Rejectedexecutionhandler handler: rejects the task's processing policy. When the thread pool has been shut down, or if threads have reached maximumpoolsize and the task queue is full, the newly committed task will be denied execution. The four types of rejection tasks provided by the thread pool are handled as follows:
Threadpoolexecutor.abortpolicy: The default reject processing policy, which throws a rejectedexecutionexception Run-time exception when the task is rejected;
Threadpoolexecutor.discardpolicy: simply discard tasks;
Threadpoolexecutor.discardoldestpolicy: Discards the first task in the queue and attempts to perform the task again;
Threadpoolexecutor.callerrunspolicy: Perform this task in the thread that calls the Execute method, which provides a simple feedback mechanism to reduce the rate at which new tasks are committed. 1.2 Threadpoolexecutor class hierarchy Relationship
The Threadpoolexecutor class is defined as follows:
public class Threadpoolexecutor extends abstractexecutorservice{....
Visible from the above code, Threadpoolexecutor inherits the Abstractexecutorservice class. The Abstractexecutorservice class is defined as follows:
Public abstract class Abstractexecutorservice implements Executorservice {...
As is seen from the above code, the Abstractexecutorservice class is an abstract class and implements the Executorservice interface. The Executorservice interface is defined as follows:
Public interface Executorservice extends executor{....
Visible from the above code, the Executorservice interface inherits the executor interface. The Excutor interface is defined as follows:
Public interface executor{...
Executor is a top-level interface. 2. Thread pool settings 2.1 thread pool status
The Threadpoolexecutor class defines the thread pool state as follows:
private static final int count_bits = integer.size-3;
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;
Visible from the above code, the thread pool A total of running, SHUTDOWN, STOP, tidying, terminated these five states:
RUNNING: In this state, the thread pool accepts the new task and executes the task waiting to be performed in the queue;
SHUTDOWN: In this state, the thread pool no longer accepts new tasks, but continues to process tasks that are already in the queue;
STOP: In this state, the thread pool does not accept new tasks, does not handle tasks that are already in the queue, and interrupts the tasks that are being performed;
Tidying: In this state, all tasks in the thread pool are terminated, the number of worker threads is 0, and the internal terminated () method is automatically executed;
Terminated: The internal terminated () method is completed. transition between 2.2 thread pool states
RUNNING-> SHUTDOWN: Call SHUTDOWN method;
(RUNNING or SHUTDOWN)-> STOP: Invokes the Shutdownnow method;
SHUTDOWN-> tidying: When both the queue and the thread pool are empty;
STOP-> tidying: When the thread pool is empty;
Tidying-> terminated: When the internal terminated method is completed; 2.3 thread pool shutdown
The Threadpoolexecutor class provides two methods for closing the thread pool, respectively, the shutdown () and Shutdwonnow () methods:
Shutdown (): After the method is executed, the thread is not terminated immediately, waits for all tasks in the task queue to complete, but does not accept the new task;
Shutdownnow (): After this method is executed, the newly committed task is blocked and the running thread is interrupted. You also remove tasks from the task queue and add them to the list of lists to return. 3. Execute method Internal implementation
In the Threadpoolexecutor class, the most core task submission method is the Execute method, and here we parse the internal implementation of the Execute method:
public void Execute (Runnable command) {if (command = NULL)//If the passed task is Null,execute the method will throw the nullpointexception exception
throw new NullPointerException (); int c = Ctl.get ();
The CTL is a atomicinteger type variable used to hold the current thread pool status if (Workercountof (c) < corepoolsize) {//workercountof Returns the number of worker threads in the current state if (Addworker (command, True))//Call the Addworker function, return True if the thread was successfully added;
otherwise returns false return;
c = Ctl.get ();
} if (IsRunning (c) && workqueue.offer (command) {//If the thread pool is in the running state but has reached corepoolsize thread, add to the task queue
int recheck = Ctl.get (); if (! isrunning (Recheck) && Remove (command)//Remove the newly submitted task reject (command) from the queue;
Discard task Else if (workercountof (recheck) = = 0) Addworker (null, FALSE);
else if (!addworker (command, FALSE))//If the thread pool is not in the running state, or if the task queue is full, call Addworker, and the parameter is set to False, trying to create a margin thread
Reject (command); }
The source code for the
Addworker function is as follows:
Private Boolean Addworker (Runnable Firsttask, Boolean core) {retry:for (;;) {int c = ctl.get (); Gets the current thread pool state int rs = runstateof (c);
Lower 29 position of State C 0//Check If queue empty only if necessary. if (rs >= SHUTDOWN &&!)
(rs = = SHUTDOWN && Firsttask = = null &&! workqueue.isempty ())) return false; returns false for (;;) if it is in a stop state, or if the task parameter passed is not NULL.
{int WC = Workercountof (c);
if (WC >= CAPACITY | | WC >= (Core corepoolsize:maximumpoolsize))//If the core is true, it represents the thread to create the kernel thread return FA Lse Unable to create core thread or margin thread if (Compareandincrementworkercount (c))//cas operation increases the number of worker threads in the current thread pool break r
Etry; c = Ctl.get ();
Re-read CTL if (runstateof (c)!= RS)//state change Continue retry; Else CAS failed due to workercount;
Retry Inner Loop}} Boolean workerstarted = false;
Boolean workeradded = false;
Worker w = null; try {w = new Worker (firsttask); New Worker object, the worker class is the inner class final Thread t = w.thread; W.thread is constructed via thread factory threadfactory if (t!= null) {final Reentrantlock Mainlock = This.mainlo
ck Mainlock.lock ();
Gets the Mainlock lock try {//recheck while holding lock in the Threadpoolexecutor class.
Threadfactory failure or if//Shut down before lock acquired.
int rs = runstateof (Ctl.get ());
if (Rs < SHUTDOWN | | (rs = = SHUTDOWN && firsttask = null))
{if (t.isalive ())//PreCheck that T-startable throw new Illegalthreadstateexception (); Workers.add (w);
Add a new Worker object to the hashset type variable workers int s = Workers.size ();
The IF (S > Largestpoolsize)//largestpoolsize is used to record the maximum number of threads that the thread pool has reached largestpoolsize = s;
Workeradded = true;
finally {Mainlock.unlock ();
} if (workeradded) {T.start ();
Workerstarted = true;
finally {if (! workerstarted) addworkerfailed (w);
return workerstarted; }
4. Configuration strategy for thread pool size
You typically configure the size of the thread pool based on the type of task:
If it is CPU-intensive, usually need to squeeze the CPU as much as possible, the number of threads can be set to ncpu+1;
If it is IO-intensive, the reference value can be set to 2*NCPU;
Reference blog:
Http://www.cnblogs.com/dolphin0520/p/3932921.html