Java Thread Pool Explained
Thread Pool Explained
Thread pooling uses pooling ideas to effectively manage the life cycle of threads, reducing the consumption of resources each time you get, and improving resource utilization. Similar pooling implementations include database connection pooling, HTTP connection pooling, and so on.
mileage
- Reduced overhead for thread creation and destruction
- Improved responsiveness
- Makes threads easier to manage
Common Usage Scenarios
- High-volume tasks with short processing time: Effective use of the thread pool to reduce the consumption of thread creation and destruction
- When you need to limit the number of threads: the more threads the greater the consumption of resources, the thread pool can be set to limit the maximum number of threads
- Asynchronous execution of a batch of tasks that do not require immediate feedback: asynchronous execution of tasks to reduce system response time
Introduction of Thread Pooling: The Executor Framework
The Executor framework, introduced in Java 5, optimizes and upgrades the traditional thread manipulation methods to make them more flexible and easier to manage for different scenarios, and its core jar packages are
Abbreviations
JUC
. In addition, and very importantly, the framework avoids theThis escaped.
Question.this escape: means that before the return of the constructor, other threads hold a reference to the object, and at this time, when the reference to the object calls its methods, there may be bad troubleshooting exceptions.
The Executor framework consists of three main parts
-
Mission:
Runnabale/Callable
can be used byThreadPoolExecutor
maybeScheduledThreadPoolExecutor(predecessorThreadPoolExecutor)
fulfillment -
Implementation: by realizing
Executor
subinterface of an interfaceExecutorService
To construct a relatively complete thread pool execution system -
Return value: one of the advantages of thread pooling, by implementing the
Futrure
interfacesFutureTask
class gets the results of the asynchronous execution into the -
Main thread creation
Runnable
orCallable
task object, and then puts the implementedRunnbale
orCallable
hand overExecutorService
Implementation:(Runnable command)
Or.Runnable
objects orCallable
The object is submitted to theExecutorService
Implementation ((Runnable command)
) -
If the execution of the
()
,ExecutorService
Returns an object that implements theFuture
The object of the interface (submit()
will return aFuturesTask
Object.FutureTask
RealizedRunnable
You can createFutureTask
Then it goes straight to theExecutorService
Implementation;execute
(then the exception will be printed out) -
Finally, the main thread executes
()
method waits for the task execution to complete. You can also wait for the task to complete by using the(boolean mayInterruptIfRunning)
to cancel this task execution.
in order to
ThreadPoolExecutor
As an example.ThreadPoolExecutor
inheritedAbstractExecutorService
(abstract function) of the submit method and implements theAbstractExecutorService
come from (a place)Executor
interfacesexecute
method of the thread pool, so it's not necessary to call thesubmit
method is passed through theThreadPoolExecutor
(used form a nominal expression)execute
To place the task (Runnabale/Callable
coreRunnableFuture
object) is added to the work queue (addWorker
method is implemented), and the return value is passed through theRunnableFuture
returned in the form of an object.
This simply means that the main thread willRunnabale/Callable
The object is passed through thesubmit
method is submitted to the thread pool, which executes multithreaded tasks according to different strategies through internal scheduling and then returns theFutrure
targetget
method to retrieve the execution result.
ThreadPoolExecutor Class
Thread Pool Implementation Classes
ThreadPoolExecutor
beExecutor
The core classes of the framework
After the main thread submits the task
- The first step is to determine whether the number of threads in the core thread pool is full, if it is not full then create threads, if it is full then go to step 2
- The second step is to determine whether the waiting queue is full or not, if it is not full, then join the queue, if it is full, then go to the third step.
- The third step is to determine whether the maximum number of threads is full, if not then create threads, if it is full then process according to the set rejection policy
Parameter Description:
-
corePoolSize
: Number of core threads, number of threads that can be processed in the first place -
maximumPoolSize
: the maximum number of threads, when the core thread pool as well as the queue are full, the thread pool will be expanded to the maximum number of threads -
workQueue
: When the core thread pool is full, the queue can be used for staging tasks that come in later. -
keepAliveTime
: When the number of threads is greater than the number of core threads, threads whose idle time exceeds this value will be recycled until they are reduced to the number of core threads. -
unit
:keepAliveTime
Time unit of the parameter -
threadFactory
: the thread factory.executor
Used when creating threads -
handler
: The denial policy thread pool has reached its maximum number of threads, and the queue is full, so any more tasks coming in will trigger the denial policy.
Rejection strategy.
-
AbortPolicy
: Rejects the task and throws an exceptionRejectedExecutionException
-
CallerRunsPolicy
: performs tasks directly in the calling thread, affecting performance -
DiscardPolicy
: Rejects the task, does not report an exception and does not do anything about it -
DiscradOldestPolicy
: Reject the earliest tasks and perform the newest ones
There are a lot of thread pool related content, the article focuses on the introduction, if you want to look deeper into one of the elements, you can refer to the source code of the way, so that you can most intuitively see the internal composition and the various elements of how to cooperate with each other to solve the problem of the implementation of the thread pool.