Java Multithreading series: Juc thread pool: 03 thread pool principle (ii)

Source: Internet
Author: User
Tags cas

Overview

In the previous chapter, "Java Multithreading Series--" Juc thread pool "02 Thread pool principle (a)" describes the data structure of the thread pool, this chapter will be analyzed through the source code of the threads pools, to explain the threading pooling. The content includes:
Line Pooling Example
Reference code (based on JDK1.7.0_40)
Line Cheng Code Analysis
(i) Creating the thread pool
(ii) Adding tasks to the thread pool
(iii) Close the thread pool

Reprint Please specify source: http://www.cnblogs.com/skywang12345/p/3509954.html

Line Pooling Example

Before analyzing the thread pool, look at a simple line pooling example.

1 Import java.util.concurrent.Executors; 2 Import Java.util.concurrent.ExecutorService; 3  4 public class ThreadPoolDemo1 {5  6 public     static void Main (string[] args) {7         //Create a thread pool that can reuse a fixed number of threads 8
   executorservice pool = Executors.newfixedthreadpool (2); 9         //Create implements the Runnable interface object, the thread object of course also implements the Runnable interface of ten         thread ta = new MyThread (); one         thread TB = new MyThread ();         the thread TC = new MyThread (),         the thread td = New MyThread (), and         the thread te = new MyThread ();         Line implementation of         Pool.execute (TA),         pool.execute (TB),         Pool.execute (TC),         Pool.execute (TD); 20         Pool.execute (TE);         //Close thread pool         pool.shutdown ();     }24}25-class MyThread extends thread {27 28< c20/> @Override29 public     void Run () {         System.out.println (Thread.CurrentThread (). GetName () + "is running.");     }32}

Operation result :

Pool-1-thread-1 is Running.pool-1-thread-2 is running.pool-1-thread-1 are Running.pool-1-thread-2 is Running.pool-1-thread-1 is running.

example, including the creation of a thread pool, adding a task to the thread pool, and shutting down the thread pools are 3 main steps. Later, we will analyze the threadpoolexecutor from these 3 aspects.

Reference code (based on jdk1.7.0_40)

Executors full Source

View Code

Threadpoolexecutor Full Source

View Code

Line Cheng Code Analysis

(i) Creating the thread pool

The following Newfixedthreadpool () describes the thread pool creation process.

1. Newfixedthreadpool ()

Newfixedthreadpool () defined in Executors.java, the source code is as follows:

public static Executorservice newfixedthreadpool (int nthreads) {    return new Threadpoolexecutor (Nthreads, Nthreads,                                  0L, Timeunit.milliseconds,                                  new linkedblockingqueue<runnable> ());}

Description : The Role of newfixedthreadpool (int nthreads) is to create a thread pool, and the capacity of the thread pool is nthreads.
Newfixedthreadpool (), when calling Threadpoolexecutor (), passes a linkedblockingqueue () object, and Linkedblockingqueue is a blocking queue implemented by the one-way list. In a thread pool, this is the blocking queue that enables "some tasks to block waiting when the number of tasks in the threads pool exceeds the number of allowed tasks."
For details on the implementation of Linkedblockingqueue, readers can refer to the "Java Multithreaded Series-" Juc collection "08 Linkedblockingqueue".

2. Threadpoolexecutor ()

Threadpoolexecutor () defined in Threadpoolexecutor.java, the source code is as follows:

Public threadpoolexecutor (int corepoolsize,                          int maximumpoolsize,                          long KeepAliveTime,                          timeunit Unit,                          blockingqueue<runnable> WorkQueue) {This    (corepoolsize, maximumpoolsize, KeepAliveTime, Unit, WorkQueue,         executors.defaultthreadfactory (), DefaultHandler);}

Description : This function is actually another constructor that calls Threadpoolexecutor. The source code for this function is as follows:

 public threadpoolexecutor (int corepoolsize, int maximumpoolsize, lo Ng KeepAliveTime, timeunit unit, blockingqueue<runnable> WorkQueue  , Threadfactory threadfactory, Rejectedexecutionhandler handler) {if        (Corepoolsize < 0 | |        Maximumpoolsize <= 0 | |        Maximumpoolsize < Corepoolsize | |    KeepAliveTime < 0) throw new IllegalArgumentException ();    if (WorkQueue = = NULL | | threadfactory = = NULL | | handler = = NULL) throw new NullPointerException ();    Core Pool Size this.corepoolsize = corepoolsize;    Max Pool Size this.maximumpoolsize = maximumpoolsize;    Waiting queue for thread pool This.workqueue = WorkQueue;    This.keepalivetime = Unit.tonanos (KeepAliveTime);    Thread Factory Object this.threadfactory = Threadfactory; Handle of the Deny policy This.handler = handler;} 

description : In the constructor of Threadpoolexecutor (), the initialization work is performed.
Corepoolsize, maximumpoolsize, Unit, KeepAliveTime, and workqueue the values of these variables are known, and they are all passed through Newfixedthreadpool (). Here's a look at the Threadfactory and handler objects.

2.1 Threadfactory

The threadfactory in the thread pool is a thread factory, and thread pool creation threads are all done through thread factory objects (threadfactory).
The Threadfactory object referred to above is returned by Executors.defaultthreadfactory (). Executors.java in the defaultthreadfactory () source code is as follows:

public static Threadfactory Defaultthreadfactory () {    return new defaultthreadfactory ();}

Defaultthreadfactory () returns the Defaultthreadfactory object. Executors.java in the defaultthreadfactory () source code is as follows:

Static Class Defaultthreadfactory implements Threadfactory {private static final Atomicinteger Poolnumber = new Atomic    Integer (1);    Private final Threadgroup Group;    Private final Atomicinteger threadnumber = new Atomicinteger (1);    Private final String Nameprefix;        Defaultthreadfactory () {SecurityManager s = System.getsecuritymanager (); Group = (s! = null)?        S.getthreadgroup (): Thread.CurrentThread (). Getthreadgroup ();    Nameprefix = "pool-" + poolnumber.getandincrement () + "-thread-";    }//provides the API for creating threads.                              Public thread Newthread (Runnable r) {//thread corresponding task is Runnable object R thread t = new Thread (group, R,        Nameprefix + threadnumber.getandincrement (), 0);        Set to "Non-daemon Thread" if (T.isdaemon ()) T.setdaemon (false);  Set priority to "Thread.norm_priority" if (t.getpriority ()! = thread.norm_priority)          T.setpriority (thread.norm_priority);    return t; }}

Description : The role of Threadfactory is to provide a thread factory that creates the functionality of the thread.
It is provided by Newthread () to provide the ability to create threads, the following is simply said Newthread (). Newthread () Creates a thread that corresponds to the Runnable object, which creates threads that are "non-daemon Threads" and "thread priority is thread.norm_priority".

2.2 Rejectedexecutionhandler

Handler is a handle to the deny policy in Threadpoolexecutor. The so-called deny policy, when you add a task to the thread pool, the thread pool rejects the corresponding policy that the task takes.
The thread pool defaults to the DefaultHandler policy, which is the AbortPolicy policy. In the AbortPolicy policy, the thread pool throws an exception when rejecting a task!
DefaultHandler is defined as follows:

private static final Rejectedexecutionhandler DefaultHandler = new AbortPolicy ();

The source code of AbortPolicy is as follows:

public static class AbortPolicy implements Rejectedexecutionhandler {public    AbortPolicy () {}    //throws an exception    public void Rejectedexecution (Runnable R, Threadpoolexecutor e) {        throw new rejectedexecutionexception ("Task" + r.to String () +                                             "rejected from" +                                             e.tostring ());}    }

(ii) Adding tasks to the thread pool

1. Execute ()

Execute () is defined in Threadpoolexecutor.java and the source code is as follows:

public void Execute (Runnable command) {//If the task is null, an exception is thrown.    if (command = = null) throw new NullPointerException (); Gets the int value corresponding to the CTL.    The int value holds the "number of tasks in the thread pool" and the "Wire pool state" information int c = Ctl.get ();    When the number of tasks in the thread pool < core pool size is less than corepoolsize tasks in the thread pool.    Creates a new thread by Addworker (command, true) and adds the task (command) to the thread, and then starts the thread to perform the task.        if (Workercountof (c) < corepoolsize) {if (Addworker (command, True)) return;    c = Ctl.get ();    }///When the number of tasks in the thread pool >= "core pool Size",//And when the thread pool is in allowed state, try adding the task to the blocking queue.        if (IsRunning (c) && workqueue.offer (command)) {//Confirm the thread pool status again, delete the task if the thread pool terminates abnormally, and then execute the content of the corresponding Deny policy through reject ().        int recheck = Ctl.get ();        if (! isrunning (Recheck) && Remove (command)) reject (command);        Otherwise, if the number of tasks in the thread pool is 0, a new thread is tried by Addworker (null, FALSE), and the task for the new thread is null.    else if (workercountof (recheck) = = 0) Addworker (null, FALSE); Create a new thread by Addworker (command, FALSE) and add the Task (command) to the thread;Start the thread to perform the task.    If Addworker (command, false) execution fails, the content of the corresponding deny policy is executed through reject (). else if (!addworker (command, False)) reject (command);}

Description : The Role of Execute () is to add the task to the thread pool for execution. It will be processed in 3 different situations:
Scenario 1 -If the thread pool is in the number of tasks < core pool size, which is less than corepoolsize tasks in the pool of threads, create a new thread and add the task to the thread for execution.
Scenario 2 --If the "number of tasks in the thread pool" >= "core pool Size" and "thread pool is allowed", then the task is added to the blocking queue to block the wait. In that case, the status of the thread pool is confirmed again, and the task is removed from the blocking queue if the thread pool state that is read for the 2nd time and the thread pool state that is read for the 1th time are different.
Case 3 --not in either of the above two cases. In this case, you try to create a new thread and add the task to the thread to execute it. If execution fails, the task is rejected by reject ().

2. Addworker ()

The source code of Addworker () is as follows:

Private Boolean Addworker (Runnable Firsttask, Boolean core) {retry://Update the "thread pool status and Count" tag, which updates the CTL. for (;;) {//Gets the int value corresponding to the CTL.        The int value holds the "number of tasks in the thread pool" and the "Wire pool state" information int c = Ctl.get ();        Gets the thread pool status.        int rs = runstateof (c); Validity Check if (rs >= SHUTDOWN &&!            (rs = = SHUTDOWN && Firsttask = = null &&! workqueue.isempty ()))        return false; for (;;)            {//Gets the number of tasks in the thread pool.            int WC = Workercountof (c);            Returns False if the number of tasks in the thread pool exceeds the limit.                if (WC >= Capacity | |            WC >= (Core corepoolsize:maximumpoolsize)) return false; The value of C is +1 by using the CAS function.            If the operation fails, the loop exits.            if (Compareandincrementworkercount (c)) break retry;  c = Ctl.get ();            Re-read CTL//Check the thread pool status, if it is different from the previous state, start again from retry.            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;    Add tasks to the thread pool, and start the threads where the tasks are located.        try {final Reentrantlock mainlock = This.mainlock;        Creates a new worker and specifies the first task that Firsttask is the worker.        w = new Worker (firsttask);        Gets the thread that the worker corresponds to.        Final Thread t = w.thread;            if (t! = null) {//Get lock Mainlock.lock ();                try {int c = ctl.get ();                int rs = runstateof (c);                    Confirm "Thread pool status" if (Rs < SHUTDOWN | | (rs = = SHUTDOWN && Firsttask = = null)) {if (t.isalive ())//PreCheck that T is startable throw new Illegalthreadstatee                    Xception ();                    Add the Worker object (W) to the Worker collection (workers) of the thread pool Workers.add (w);           Update Largestpoolsize int s = workers.size ();         if (S > largestpoolsize) largestpoolsize = s;                Workeradded = true;            }} finally {//release lock Mainlock.unlock ();             }//If the task is successfully added to the thread pool, the thread that contains the task is started.                if (workeradded) {T.start ();            Workerstarted = true;    }}} finally {if (! workerstarted) addworkerfailed (w);    }//Returns whether the task is started. return workerstarted;}

Description :
The role of Addworker (Runnable Firsttask, Boolean core) is to add a task (firsttask) to the thread pool and start the task.
Core is true, the corepoolsize is the limit, if "the number of tasks in the thread pool >=corepoolsize", the return False;core to False, then the maximumpoolsize as the boundary, if " The number of tasks already in the thread pool >=maximumpoolsize "returns false.
Addworker () continuously attempts to update the CTL state through a for loop, and the CTL records the number of tasks in the thread pool and the thread pooling state.
After the update succeeds, the task is added to the thread pool through the try module and the thread where the task is started.

From Addworker (), we can clearly see that the thread pool creates a worker object for a task when it adds a task, while a Workder object contains a thread object. (01) Adding a Worker object to the thread's workers collection enables the task to be added to the thread pool. (02) The task is performed by starting the thread threads corresponding to the worker.

3. Submit ()

To add a point, the submit () is actually implemented by invoking execute (), with the following source code:

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

(iii) Close the thread pool

The source code of shutdown () is as follows:

public void shutdown () {    final reentrantlock mainlock = This.mainlock;    Get lock    Mainlock.lock ();    try {        //check whether the thread pool's threads have permissions.        checkshutdownaccess ();        Sets the status of the thread pool to off state.        advancerunstate (SHUTDOWN);        Threads that are idle in the thread pool.        interruptidleworkers ();        The hook function does not have any action in the Threadpoolexecutor.        OnShutdown ();//hook for Scheduledthreadpoolexecutor    } finally {        //release lock        Mainlock.unlock ();    }    Attempt to terminate thread pool    tryterminate ();}

Description : The role of Shutdown () is to close the thread pool.

Java Multithreading class: Juc thread pool: 03 thread pool principle (b) (EXT)

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.