JDK Source code parsing--executors executorservice threadpoolexecutor thread pool

Source: Internet
Author: User

0. IntroductionExecutors is a factory and tool method for Executor, Executorservice, Threadfactory, and callable classes.


I. Source code parsing

    1. Create a fixed-size thread pool: Reduce the overhead of thread creation by reusing threads in a shared unbounded queue. When all the threads are performing the task, the new task waits in the queue until a thread is idle. Because of a thread break caused by a failure before execution, the new thread will replace it if it needs to continue with the next task. Threads in the thread pool persist until they are explicitly shutdown out.
public static Executorservice newfixedthreadpool (int nthreads) {    return new Threadpoolexecutor (Nthreads, Nthreads,                                  0L, Timeunit.milliseconds,                                  new linkedblockingqueue<runnable> ());}


Returns an object of the Threadpoolexecutor class that uses the passed-in parameters and the default thread factory and the processing that is denied execution. Corepoolsize: The number of threads in the thread pool, unless allowcorethreadtimeout is set, Otherwise, if the thread is idle or in the maximumpoolsize: the maximum number of threads allowed in the thread pool KeepAliveTime: When the number of threads is greater than corepoolsize, if the idle thread in KeepAliveTime is not executed, The thread will be terminated unit:keepalivetime time unit Workqueue: Save execute () submitted task
Public threadpoolexecutor (int corepoolsize,                          int maximumpoolsize,                          long KeepAliveTime,                          timeunit Unit,                          blockingqueue<runnable> WorkQueue) {This    (corepoolsize, maximumpoolsize, KeepAliveTime, Unit, WorkQueue,         executors.defaultthreadfactory (), DefaultHandler);}
you can see the fixed size thread pool, corepoolsize and Maximumpoolsize pass in the same parameters.

    1. Creates a thread pool for a single thread. tasks are guaranteed to be executed sequentially because there is only one worker thread. Unlike Newfixedthreadpool (1), this does not guarantee task order execution. both Corepoolsize and maximumpoolsize are 1.
public static Executorservice Newsinglethreadexecutor () {    return new Finalizabledelegatedexecutorservice        ( New Threadpoolexecutor (1, 1,                                0L, Timeunit.milliseconds,                                new Linkedblockingqueue<runnable> ()));}


    1. Create a thread pool that can be automatically expanded on demand, but will prioritize the reuse of idle threads in the thread pool. This type of thread pool will greatly increase the number of programs that perform many short-lived asynchronous tasks. If thread pool threads are in use and new tasks arrive, a thread-to-thread pool is added. If the thread is idle within 60 seconds, the thread pool is terminated. corepoolsize is 0, and if thread 60s is idle, it will be moved to the pool.
public static Executorservice Newcachedthreadpool () {    return new Threadpoolexecutor (0, Integer.max_value,                                  60L , Timeunit.seconds,                                  new synchronousqueue<runnable> ());}


    1. Create a thread pool that dispatches commands after a certain delay time, or a periodic execution.
public static Scheduledexecutorservice newscheduledthreadpool (int corepoolsize) {    return new Scheduledthreadpoolexecutor (corepoolsize);}


    1. The thread pool is created and then the task is executed. Look at the Execute method in the inner class Delegatedexecutorservice: You can see that the Task execution policy (single thread serial, multithreaded parallel) and the specific execution separation of the task is a typical command pattern.
Static Class Delegatedexecutorservice extends Abstractexecutorservice {private final executorservice E;    Delegatedexecutorservice (Executorservice executor) {e = executor;}    public void Execute (Runnable command) {e.execute (command);}    public void shutdown () {E.shutdown ();}    Public list<runnable> Shutdownnow () {return E.shutdownnow ();}    public boolean IsShutDown () {return E.isshutdown ();}    public Boolean isterminated () {return e.isterminated ();} public boolean awaittermination (long timeout, timeunit unit) throws Interruptedexception {return e.awaitter    Mination (timeout, unit);    Public future<?> Submit (Runnable Task) {return E.submit (Task);    } public <T> future<t> submit (callable<t> Task) {return E.submit (Task);    } public <T> future<t> submit (Runnable task, T result) {return E.submit (task, result); } public <T> list<future<t>> InvokeAll (Collection<?    Extends callable<t>> tasks) throws Interruptedexception {return E.invokeall (tasks);                                         } public <T> list<future<t>> invokeall (collection<? extends callable<t>> tasks, Long timeout, timeunit unit) throws Interruptedexception {return E.invokeall    (Tasks, timeout, unit);  } public <T> T invokeany (collection<? extends callable<t>> tasks) throws Interruptedexception,    executionexception {return e.invokeany (tasks); } public <T> T invokeany (collection<? extends callable<t>> tasks, long time Out, Timeunit unit) throws Interruptedexception, Executionexception, timeoutexception {return E.invokeany (t    asks, timeout, unit); }}


    1. When the thread pool was created, Threadpoolexecutor was instantiated, so the Execute () method above actually calls Threadpoolexecutor's execute: The given task may be executed at some point in the future. It could be a new thread execution, or a thread from a thread. If the task cannot be executed, it may be that the executor has been shutdown, or it may have reached the execution threshold of the thread pool, and the task was denied execution in processor processing.
public void Execute (Runnable command) {    if (command = = null)        throw new NullPointerException ();    int c = Ctl.get ();    if (Workercountof (c) < corepoolsize) {        if (addworker (command, True))            return;        c = Ctl.get ();    }    if (IsRunning (c) && workqueue.offer (command)) {        int recheck = Ctl.get ();        if (! isrunning (Recheck) && Remove (command))            reject (command);        else if (workercountof (recheck) = = 0)            Addworker (null, FALSE);    }    else if (!addworker (command, false))        reject (command);}


See this, actually found that the core implementation of the thread pool is in the threadpoolexecutor inside, so first introduce the role of the Threadpoolexecutor class:
You can see the position in the hierarchy of the Threadpoolexecutor class, which is the complete implementation of the abstract method and interface, that is, the core code in this class.
One executorservice performs each task may use one or more threads in the thread pool, and the thread pool is created by the Executors factory.The thread pool solves two different problems:
    • When performing a large number of asynchronous tasks, the thread pool reduces the creation of threads to reduce overhead and improve performance
    • Provides management of resources, including the consumption of threads when performing a series of tasks. Each threadpoolexecutor also stores some basic data, such as the number of tasks completed

To use it in a broader context, this class provides a number of adjustable parameters and extended hooks. In any case, it is more convenient to use executors to create a thread pool.
This main thread pool controls the state of the CTL, using Atomicinteger to store two conceptual fields Workercount (thread PoolNumber of active threads) and Runstate (thread PoolRunning, shuting down, etc.)
Private final Atomicinteger ctl = new Atomicinteger (Ctlof (RUNNING, 0));



The execute () method above has three processing steps:
    • If the thread being running (that is, the worker thread) is less than corepoolsize (Workercountof (c) < corepoolsize), try to create a new thread and put the incoming command (Task) as its first task 。 Call Addworker (command, True) to automatically check runstate and Workcount to return FALSE when the thread cannot be incremented. Add successful direct return, can not be added depends on the following steps
    • If the queue is successfully placed (if (IsRunning (c) && workqueue.offer (command)) WorkQueue is a queued blocking queue), then two more times are required to check if the thread pool is shut Down (died before this check-up after the last check). So we re-check the status, if the thread pool stops, roll back into the queue operation, or if there is no working thread to open a new thread (Addworker (null, FALSE);)
    • If you cannot get the task into the blocking queue, then try adding a new thread. If the new thread fails, it may be that the thread pool shut down or the thread pool is saturated (to maxpoolsize), so then discard the task.

Tasks are wrapped in a class called worker, worker inherits AQS to implement task increment/delete synchronization control, and HashSet is used to save worker threads. If the worker thread is greater than corepoolsize, the worker thread is not created, but instead is placed in a blockingqueue queue. If the blockingqueue of the bounded queue is full, try increasing the thread-to-wire pool, but the total number of threads is less than maxpollsize.

Addworker () Method: Check the current state of the thread pool and the boundary condition of the number of threads to see if the worker thread can be increased. If so, the worker thread counts the response adjustment, and, if possible, the new worker thread is created, started, and runs its first task. This method returns False if the thread pool is stop or is shut down. This method also returns False if threading factory (thread Factory) failed to create a thread. If thread creation fails, either the thread factory returns NULL, or exception (usually OOM), is rolled back.
Parameter firsttask: The first task that a new thread should run. If the worker thread is less than Corepoolsize,worker and the first task that is initialized is created to bypass the queued process, or the queue is full. Initializing an idle thread is usually done by prestartcorethread or by replacing a worker thread that has died. Core: If true, use corepoolsize as the boundary, otherwise use maximumpoolsize as the boundary. (Boolean is used here instead of passing in the actual value because the incoming value can be changed in the incoming process, and the values are read directly in the method).
Private Boolean Addworker (Runnable Firsttask, Boolean core) {retry:for (;;)        {int c = ctl.get ();        int rs = runstateof (c);        Check If queue empty only if necessary. if (rs >= SHUTDOWN &&!            (rs = = SHUTDOWN && Firsttask = = null &&! workqueue.isempty ()))        return false; for (;;)            {int WC = Workercountof (c);                if (WC >= Capacity | |            WC >= (Core corepoolsize:maximumpoolsize)) return false;            if (Compareandincrementworkercount (c)) break retry;  c = Ctl.get ();            Re-read CTL if (runstateof (c)! = RS) continue retry; Else CAS failed due to workercount change;    Retry Inner Loop}} Boolean workerstarted = false;    Boolean workeradded = false;    Worker w = null;        try {final Reentrantlock mainlock = This.mainlock; W = nEW Worker (Firsttask);        Final Thread t = w.thread;            if (t! = null) {Mainlock.lock ();                try {//recheck while holding lock.                Threadfactory failure or if//Shut down before lock acquired.                int c = Ctl.get ();                int rs = runstateof (c);                    if (Rs < SHUTDOWN | | (rs = = SHUTDOWN && Firsttask = = null)) {if (t.isalive ())//PreCheck that T is startable throw new Illegalthreadstatee                    Xception ();                    Workers.add (w);                    int s = workers.size ();                    if (S > largestpoolsize) largestpoolsize = s;                Workeradded = true;            }} finally {Mainlock.unlock ();                } if (workeradded) {T.start ();            Workerstarted = true; }        }    } finally {if (! workerstarted) addworkerfailed (w); } return workerstarted;}












JDK Source code parsing--executors executorservice threadpoolexecutor thread pool

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.