Java thread Pool Framework source code Analysis

Source: Internet
Author: User

Related class Executor,executors. Abstractexecutorservice. Executorservice

Executor: The top-level interface of the entire thread pool runner framework.

Defines an Execute method. The core method of the entire thread-runner framework.

Public interface Executor {    void execute (Runnable command);}

Executorservice: This is an interface that inherits from executor, which defines shutdown. Shutdownnow,awaittermination,submit. InvokeAll and other methods.

Abstractexecutorservice: Implements the method of Submit,invokeall in the Executorservice interface.

  Public future<?

> Submit (Runnable Task) { if (task = = null) throw new NullPointerException (); runnablefuture<void> ftask = newtaskfor (task, null); Execute (ftask); return ftask; } Public <T> future<t> Submit (Runnable task, T result) { if (task = = null) throw new NullPointerException (); runnablefuture<t> ftask = newtaskfor (task, result); Execute (ftask); return ftask; } Public <T> future<t> Submit (callable<t> Task) { if (task = null) throw new NullPointerException () ; runnablefuture<t> ftask = newtaskfor (Task); Execute (ftask); return ftask; }

Over here. The task submitted by the all Submit method finally calls the Execute method. Execute is the method defined in interface executor, Abstractexecutorservice does not implement it,

Subclasses are required to implement this method. Threadpoolexecutor inherits the Abstractexecutorservice, which implements the Execute method. Scheduledthreadpoolexecutor inherits from

Threadpoolexecutor, and overrides the Execute method of the Threadpoolexecutor. This method is the core logic of the thread running the frame holder, and different thread pool actors have different implementation logic.


The function of Abstractexecutorservice is relatively simple. Implementation of the different parameters of the submit. InvokeAll method.


Threadpoolexecutor thread pool Runner: It has a core member variable:

Private final hashset<worker> workers = new hashset<worker> ();

Workers can be seen as a pool of threads used to perform tasks in Threadpoolexecutor.


A worker is a class that encapsulates a thread object and implements the Runnable interface.

Encapsulation thread is very easy to understand, because it uses thread to execute the runnable task submitted by the Execute method.

But why does it inherit the Runnable interface?

The following is a worker source code that excludes part of the code:

  Private Final class Worker        extends Abstractqueuedsynchronizer        implements Runnable    {     final Thread thread;                Runnable Firsttask;        Worker (Runnable firsttask) {            setState ( -1);             This.firsttask = Firsttask;            This.thread = Getthreadfactory (). Newthread (this);        }        public void Run () {            runworker (this);        }    }

Worker is an inner class of threadpoolexecutor, the worker itself implements the Runnable interface, encapsulates a thread object, and finally acquires a Runnable object in the constructor method. This object is the target task submitted by Threadpoolexecutor via execute.

Trace Runworker (This) method:

final void Runworker (Worker w) {Thread wt = Thread.CurrentThread ();        Runnable task = W.firsttask;        W.firsttask = null;         W.unlock ();        Boolean completedabruptly = true; try {while (task! = NULL | |                (Task = Gettask ()) = null) {W.lock ();                     if (Runstateatleast (Ctl.get (), STOP) | | (thread.interrupted () && runstateatleast (Ctl.get (), STOP)))                &&!wt.isinterrupted ()) wt.interrupt ();                    try {beforeexecute (WT, Task);                    Throwable thrown = null; try {task.run ();//The Run method of the target task is called directly here, and it is not passed to the thread object.

} catch (RuntimeException x) {thrown = x; throw x; } catch (Error x) {thrown = x; throw x; } catch (Throwable x) {thrown = x; throw new Error (x); } finally {AfterExecute (task, thrown); }} finally {task = null; w.completedtasks++; W.unlock (); }} completedabruptly = false; } finally {Processworkerexit (w, completedabruptly); } }


Look back to see how the worker is constructed:

Worker (Runnable firsttask) {        setState ( -1);         This.firsttask = Firsttask;        This.thread = Getthreadfactory (). Newthread (this);    }

It passes itself to the member variable thread.

The step that the target task is running may be that the worker's member variable, thread, invokes the worker's Run method. The worker's Run method passes itself to Runworker,runworker in the Run method that invokes the target running object.


So when did thread get run?

Here's a look at one of the other methods in Threadpoolexecutor:

   Private Boolean Addworker (Runnable Firsttask, Boolean core) {... try {final Reentrantlock            Mainlock = This.mainlock;            w = new Worker (firsttask); Final Thread t = w.thread;//Here Initializes a worker object W.                In the member variable of W, the thread is paid to T if (t! = null) {Mainlock.lock ();                    try {int c = ctl.get ();                    int rs = runstateof (c);                        if (Rs < SHUTDOWN | | (rs = = SHUTDOWN && Firsttask = = null))                        {if (t.isalive ()) throw new Illegalthreadstateexception ();                        Workers.add (w);                        int s = workers.size ();                        if (S > largestpoolsize) largestpoolsize = s;                    Workeradded = true;                }} finally {Mainlock.unlock (); } if (workeradded) {T.start ();//Call the Start method of T here.                Workerstarted = true;        }}} finally {if (! workerstarted) addworkerfailed (w);    } return workerstarted; }

Why is the design so around here, I think the main thing is that the worker not only encapsulates a thread, but also encapsulates the target task. Addworker is able to do some related operations before performing the target task after encapsulation.

Only the thread pool for Threadpoolexecutor is described here. So how this thread pool is maintained. Here are a few key parameters.

private volatile int corepoolsize;  private volatile int maximumpoolsize;  Private final blockingqueue<runnable> WorkQueue;

These three are the member variables of Threadpoolexecutor, in which Workqueue is not related to the county pool.

Workqueue is a thread-safe blocking queue.

Corepoolsize is the core size of the thread pool. Maximumpoolsize is the maximum size of the thread pool.

When submitting a new task, assume that the threadpoolexecutor thread is executing. and the number of threads is less than corepoolsize, then a new thread is created.

Assuming that the number of threads currently executing is greater than corepoolsize, it is placed in the cache queue Workqueue. Suppose the buffer queue is full. Continue creating threads until the number of threads reaches Maximumpoolsize

public void Execute (Runnable command) {        if (command = = null)            throw new NullPointerException ();        Inference assumes that the number of threads currently executing is less than corepoolsize, adding a new thread (Addworker will join a new thread. Described above), the method is returned directly.        int c = Ctl.get ();        if (Workercountof (c) < corepoolsize) {            if (addworker (command, True))                return;            c = Ctl.get ();        }        Assuming that the current number of threads executing is greater than or equal to Corepoolsize, the new task is placed in the cache queue.        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))        //Last buffer queue join fails, the join thread continues.

If a new thread fails to join, the task is rejected. reject (command); }


There are a few other parameters:

Private volatile threadfactory threadfactory//thread's factory function.

Private volatile rejectedexecutionhandler the processing class for handler;//task rejection. The private volatile long keepalivetime;//task is waiting for the.

Threadpoolexecutor has several constructor methods to initialize these parameters. The executors class simplifies these parameters to obtain a executorservice reference.

public static Executorservice newfixedthreadpool (int nthreads) {return new Threadpoolexecutor (Nthreads, Nthreads, 0L, Timeunit.milliseconds, new Linkedblockingque    Ue<runnable> ()); } public static Executorservice newfixedthreadpool (int nthreads, threadfactory threadfactory) {return new THR                                      Eadpoolexecutor (Nthreads, Nthreads, 0L, Timeunit.milliseconds,    New Linkedblockingqueue<runnable> (), threadfactory);                                      } public static Executorservice Newcachedthreadpool () {return new Threadpoolexecutor (0, Integer.max_value, 60L, Timeunit.seconds, new Synchronousqueue<runn    Able> ()); } public static Executorservice Newcachedthreadpool (Threadfactory threadfactory) {return new ThreadPoolexecutor (0, Integer.max_value, 60L, Timeunit.seconds,    New Synchronousqueue<runnable> (), threadfactory); }

The first two of these four methods have the same number of core threads and the maximum number of threads, and the total number of threads that can be executed is fixed, <=nthreads.

When the number of tasks is greater than nthreads, it is placed in the buffer queue. In the latter two methods, the number of threads is borderless, the number of core threads is 0, the maximum number of threads is the maximum value of an integer, and then it is assumed that there is no task execution within 60 seconds of the thread being destroyed. Each time a new task comes, a new thread is created or a thread that was created (a thread with no task execution within 60 seconds).

You may have questions. Since the number of core threads is 0, isn't all of the tasks on the team? So now take a look at Synchronousqueue this team, can see the introduction http://wsmajunfeng.iteye.com/blog/1629352/here.

Look back at the source code of the task submission method:

  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)) {//Here is a task in the queue, assuming that the worker is joined (encapsulated thread object)            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);    }

The blog in the link above mentions: Offer () returns immediately after placing an element in the queue, assuming that the element is taken away by another thread, and the method returns True. The offer succeeds or returns false.
Imagine that the first time you commit a task, the number of core threads is 0, there are no threads so there is no thread to fetch from Workqueue, so the Workqueue.offer command will return false, then it will go through Addworker ( command, FALSE) to create a new thread.



Java thread Pool Framework source code Analysis

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.