Deep analysis of the implementation principle of Java thread pool

Source: Internet
Author: User

Objective

Threads are scarce resources, if created indefinitely, will not only consume system resources, but also reduce the stability of the system, the reasonable use of thread pool for uniform distribution, tuning and monitoring, there are the following benefits:

1, reduce the consumption of resources;

2, improve the response speed;

3, improve the manageability of threads.

The executor framework, introduced in Java1.5, decouples the submission and execution of tasks by defining tasks and then submitting them to the thread pool, regardless of how the task executes, which thread executes it, and when it executes.

Demo

1, Executors.newfixedthreadpool (10) Initializes a thread pool containing 10 threads executor;

2, through the Executor.execute method to submit 20 tasks, each task print the current thread name;

3. The life cycle of the thread responsible for executing the task is managed by the executor framework;

Threadpoolexecutor

Executors is the factory class for the Java thread pool, which allows you to quickly initialize a thread pool that meets your business needs, such as the Executors.newfixedthreadpool method, which can generate a single threads with a fixed number of threads.

Its essence is to initialize a Threadpoolexecutor object with different parameters, the specific parameters are described as follows:

Corepoolsize

The number of core threads in the thread pool, when a task is submitted, the thread pool creates a new thread to perform the task until the current number of threads equals corepoolsize, and if the current number of threads is corepoolsize, the task that continues to commit is saved to the blocking queue, waiting to be executed If the Prestartallcorethreads () method of the thread pool is executed, the thread pool creates and starts all core threads in advance.

Maximumpoolsize

The maximum number of threads allowed in the thread pool. If the current blocking queue is full and the task continues to be submitted, a new thread is created to perform the task, provided that the current number of threads is less than maximumpoolsize;

KeepAliveTime

The time at which the thread is idle, that is, when the thread does not have a task to execute, the time to survive; By default, the parameter is only useful if the number of threads is greater than corepoolsize;

Unit

The unit of KeepAliveTime;

WorkQueue

The blocking queue used to hold the task waiting to be executed, and the task must implement the Runable interface, which provides the following blocking queue in the JDK:

1. Arrayblockingqueue: Bounded blocking queue based on array structure, sorting tasks by FIFO;

2, Linkedblockingquene: Based on the chain list structure of the blocking queue, according to FIFO sorting tasks, throughput is usually higher than arrayblockingquene;

3, Synchronousquene: A blocking queue that does not store elements, each insert operation must wait for another thread to invoke the remove operation, otherwise the insert operation is always in a blocked state, and throughput is usually higher than linkedblockingquene;

4, Priorityblockingquene: a priority of the unbounded blocking queue;

Threadfactory

The factory that creates the thread, through a custom thread factory, can set a name for each new thread that has a recognized thread.

Handler

The saturation policy of the thread pool, when the blocking queue is full and there are no idle worker threads, if you continue to submit the task, you must take a policy to handle the task, and the thread pool provides 4 strategies:

1, AbortPolicy: Directly throws the exception, the default policy;

2. Callerrunspolicy: Perform the task with the caller's thread;

3, Discardoldestpolicy: Discard the first task in the blocking queue, and perform the current task;

4, Discardpolicy: direct discard task;

It is also possible to implement the Rejectedexecutionhandler interface based on the application scenario, customizing the saturation strategy, such as logging or persisting the task that the storage cannot handle.

Exectors

The Exectors factory class provides the initialization interface for the thread pool, mainly in the following ways:

Newfixedthreadpool

Initializes a thread pool with a specified number of threads, where corepoolsize = = Maximumpoolsize, using Linkedblockingquene as the blocking queue, but does not release the thread when the thread pool has no executable task.

Newcachedthreadpool

1. Initialize a thread pool that can cache threads, default cache 60s, thread pool threads can reach Integer.max_value, i.e. 2147483647, internal use synchronousqueue as blocking queue;

2. Unlike the thread pool created by Newfixedthreadpool, Newcachedthreadpool automatically frees thread resources when there is no task execution, when the thread is idle for more than KeepAliveTime, and when a new task is submitted, if there are no idle threads, Creates a new thread to perform the task, which results in a certain amount of system overhead;

Therefore, when using this thread pool, be careful to control the number of concurrent tasks, otherwise creating a large number of threads can cause serious performance problems.

(Java Advanced programmer) Learn to communicate QQ Group: 478052716 You in the process of learning Java or in the work encountered any problems can come to the group of questions, Ali Java senior Daniel live to explain knowledge points, share knowledge, many years work experience combing and summary, with everyone comprehensive, Scientific establishment of their own technical system and technical knowledge! Can add a group to find me to the classroom link Note: Is free of development experience is not mistaken into Oh! Do not enter!

Newsinglethreadexecutor

There is only one thread in the initialized thread pool, and if the thread ends abnormally, a new thread is recreated to continue the task, and the only thread can guarantee the order in which the submitted tasks are executed, using Linkedblockingqueue as the blocking queue internally.

Newscheduledthreadpool

The initialized thread pool can periodically perform the submitted tasks within a specified time, and in the actual business scenario, the thread pool can be used to synchronize data periodically.

Implementation principle

In addition to Newscheduledthreadpool's internal implementation of a special point, several other thread pools are based on the Threadpoolexecutor class implementation.

Thread pool Internal state

The Atomicinteger variable ctl is very powerful: it uses a low 29-bit representation of thread pool threads, and a high 3-bit to represent the running state of the thread pools:

1, running:-1 << count_bits, that is, 3 bits high is 111, the thread pool of the state will receive new tasks, and handle the tasks in the blocking queue;

2, shutdown:0 << count_bits, i.e. high 3 bits 000, the thread pool in this state will not receive new tasks, but will handle the tasks in the blocking queue;

3, Stop:1 << count_bits, that is, 3 bits High is 001, the thread of this state will not receive new tasks, will not handle the tasks in the blocking queue, and will interrupt the running task;

4, Tidying:2 << count_bits, that is, 3 bits high is 010;

5, Terminated:3 << count_bits, that is, 3 bits high is 011;

Task Submission

The thread pool framework provides two ways to submit tasks, choosing different ways to meet different business requirements.

Executor.execute ()

The task submitted through the Executor.execute () method must implement the Runnable interface, and the task submitted by this method cannot get the return value, so it is not possible to determine whether the task was successfully executed.

Executorservice.submit ()

The task that is submitted by the Executorservice.submit () method can get the return value that the task finished executing.

Task execution

When a task is submitted to the thread pool, what does the thread pooling do with the task?

Execute implementation

The specific implementation process is as follows:

1, the Workercountof method according to the low 29 bits of the CTL, get the thread pool current number of threads, if the number of threads is less than corepoolsize, then execute Addworker method to create a new thread execution task, otherwise execute step (2);

2. If the thread pool is in the running state and the committed task is successfully placed in the blocking queue, perform step (3), otherwise perform step (4);

3, again check the status of the thread pool, if the thread pool is not running, and successfully remove the task from the blocking queue, then perform the Reject method processing task;

4, execute the Addworker method to create a new thread execution task, if Addwoker execution fails, then execute reject method processing task;

Addworker implementation

As you can see from the implementation of the method execute: Addworker is primarily responsible for creating new threads and performing tasks, the code is implemented as follows:

This is just the first half of the Addwoker method implementation:

1, judge the status of the thread pool, if the thread pool state value is greater than or so shutdown, then do not process the submitted task, directly return;

2, through the parameter core to determine whether the currently created thread is the core thread, if the core is true, and the current number of threads is less than corepoolsize, then jump out of the loop, start creating a new thread, the implementation is as follows:

The worker thread of the thread pool is implemented by the Woker class and, under the guarantee of the Reentrantlock lock, inserts the Woker instance into the HashSet and initiates the thread in Woker, where the worker class is designed as follows:

1, inherits the Aqs class, can conveniently realize the work thread the abort operation;

2, realizes the Runnable interface, can carry on itself as a task in the worker thread execution;

3, the currently submitted task Firsttask as a parameter to the construction method of the worker;

From the construction method implementation of the Woker class, you can find that when thread factory creates thread thread, the Woker instance itself is passed as a parameter, and when the Start method is executed, the worker's Runworker method is executed.

Runworker implementation

The Runworker method is the core of the thread pool:

1, after the thread starts, the lock is released through the Unlock method, the state of Aqs is set to 0, which indicates the interruption of operation;

2, get the first task Firsttask, execute the task of the Run method, but before the execution of the task, will be a lock operation, the task will release the lock after execution;

3, before and after the implementation of tasks, can be customized according to business scenarios BeforeExecute and AfterExecute methods;

4, Firsttask after the completion of execution, through the Gettask method to get the waiting task from the blocking queue, if there is no task in the queue, the Gettask method will be blocked and suspended, does not consume CPU resources;

Gettask implementation

The entire gettask operation is done under spin:

1, Workqueue.take: If the blocking queue is empty, the current thread will be suspended waiting, when a task in the queue is joined, the thread is awakened, the Take method returns the task, and executes;

2, Workqueue.poll: If in the KeepAliveTime time, the blocking queue or no task, then return null;

Therefore, threads implemented in the thread pool can execute tasks submitted by the user all the time.

Future and callable implementation

The task that is submitted by the Executorservice.submit () method can get the return value that the task finished executing.

In the actual business scenario, the future and callable are basically paired, and callable is responsible for producing the results, and the future is responsible for obtaining the results.

1. The callable interface is similar to runnable, except that runnable has no return value.

2, callable task in addition to return the normal results, if an exception occurs, the exception will be returned, that is, the future can get the results of asynchronous execution of the task;

3, the Future.get method will cause the main thread to block until the callable task execution is completed;

Submit implementation

The callable task submitted through the Submit method is encapsulated into a Futuretask object.

Futuretask

1, Futuretask in different stages have different states state, initialized to new;

2, the Futuretask class implements the Runnable interface, so that the Executor.execute method can be submitted futuretask to the thread pool waiting to be executed, the final execution is futuretask the Run method;

Futuretask.get implementation

The main thread is blocked internally by the Awaitdone method, which is implemented as follows:

1. If the main thread is interrupted, the interrupt exception is thrown;

2, Judge Futuretask current state, if greater than completing, indicating that the task has been completed, the direct return;

3, if the current state equals completing, indicating that the task has been executed, then the main thread only through the yield method to make up the CPU resources, waiting for it to become normal;

4, the current thread is encapsulated through the Waitnode class and added to the waiters linked list through unsafe;

5. Finally suspend the thread through the Locksupport park or Parknanos;

Futuretask.run implementation

The Futuretask.run method is executed in the thread pool, not the main thread

1, through the implementation of the callable task call method;

2. If call execution succeeds, the result is saved by set method;

3, if call execution has an exception, the exception is saved through SetException;

Set

SetException

In the set and SetException methods, the Futuretask state is modified through unsafe, and the Finishcompletion method is used to notify the main thread that the task has been completed;

Finishcompletion

1. When executing the Get method of Futuretask class, the main thread is encapsulated into Waitnode node and stored in the Waiters chain list;

2, Futuretask task after completion, through the unsafe set waiters value, and through Locksupport class Unpark method wakes the main thread;

Welcome to join the Learning Exchange Group 569772982, we learn to communicate together.

Deep analysis of the implementation principle of Java thread pool

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.