Threadpoolexecutor Source Learning (1)--Main ideas

Source: Internet
Author: User

Threadpoolexecutor is the implementation of the JDK's own concurrency package for the thread pool, starting with JDK1.5, up to the 1.6 and 1.7 of the concurrent package code I read, from the code annotations, from the hands of Doug Lea, From the code to see JDK1.7 almost rewrite the implementation of the Threadpoolexecutor code, the implementation of JDK1.6 is more obscure, inconvenient to clarify the author's ideas, so from the JDK1.7 code.

Threadpoolexecutor since it is a thread pool, the concept and significance of the so-called pool is mostly the use of resources, the thread pool is of course to make full use of thread resources, that is, to minimize the cost of new and destroyed threads, with this problem, to see how the author to achieve this goal.

A typical threadpoolexecutor call

1      PublicThreadpoolexecutor (intCorepoolsize,2                               intMaximumpoolsize,3                               LongKeepAliveTime,4 timeunit Unit,5Blockingqueue<runnable> workQueue);//Constructor6 7  Public voidExecute (Runnable command);

Typical use is a new Threadpoolexecutor object, and then call the Execute method to throw in the code that needs to be executed, and the rest of the thread control is given to Threadpoolexecutor management. From the corepoolsize,maxnumpoolsize of the constructor is well understood, but for KeepAliveTime, I used to have a non-solution, that is the maximum time that the execute thread can run, in fact:

/**     @param  KeepAliveTime When the number of threads is greater than     * The core, this is The maximum time that excess idle threads     * would wait for new tasks before terminating. */

When the number of front-line threads is greater than corepoolsize, the maximum time that an extra thread can exist without the task being executed.

Threadpoolexecutor overall code volume is still relatively large, but the core code (the processing of incoming threads, that is, the Execute method) is still relatively clear (JDK1.7). The overall idea is as follows:

1, if the number of threads is less than corepoolsize creates a new worker thread and executes the incoming Runnable object.

2, if the number of threads is greater than or equal to corepoolsize, put the current incoming Runnable object into the queue (WorkQueue, see constructor).

3, if the queue is full, create a new worker thread to execute the current incoming Runnable object.

4, if the queue is full and the number of threads reaches Maxnumpoolsize, only the incoming Runnable object can be discarded.

The code is as follows:

1      Public voidExecute (Runnable command) {2         if(Command = =NULL)3             Throw Newnullpointerexception ();4         if(poolsize >= corepoolsize | |!addifundercorepoolsize (command)) {5             if(Runstate = = RUNNING &&workqueue.offer (command)) {6                 if(runstate! = RUNNING | | poolsize = = 0)7 ensurequeuedtaskhandled (command);8             }9             Else if(!addifundermaximumpoolsize (command))TenReject (command);//Is shutdown or saturated One         } A}

There is a problem here, that is, when the queue Workqueue object is executed? Then carefully search the code execution process, each new thread is not just the incoming Runnable object directly executed, but instead:

1         /**2 * Main Run loop3          */4          Public voidrun () {5             Try {6Runnable task = Firsttask;//The first is usually the incoming runnable.7Firsttask =NULL;8                  while(Task! =NULL|| (Task = Gettask ())! =NULL) {9 RunTask (Task);TenTask =NULL; One                 } A}finally { -Workerdone ( This); -             } the}

This is the worker thread of the Run method, wherein the Gettask () is to go to workqueue inside the Runnable object and continue to execute, only when the Workerqueue is empty, the worker line friend exit the dead loop, the end of this thread.

The above is the overall realization of threadpoolexecutor ideas, but in order to ensure thread safety, the author also made a lot of effort. Choose a few more interesting places to say:

For saving the Runnable object passed in by the Execute method, the author is saved in a blockingqueue, Blockingqueue is a interface, there is a feature

/**/

That is, to get an object that may not be immediately available, this queue must be implemented in 4 ways: 1, throw an exception, 2, immediately return empty, 3, block the current call to modify the method of the thread, 4, blocking the thread waiting for a certain time, then from the queue two main method, insert, Remove will have 8 methods. If we use new Cachedthreadpool (), a common factory method for generating thread pools, Workqueue will be a Synchronousqueue object that is characterized by:

/*** A { @linkplain   Blockingqueue blocking Queue} in which all insert * operation must wait for a corresponding remove operation by another  * thread, and vice versa.  A synchronous queue does not has any * internal capacity, not even a capacity of one. You cannot * <tt>peek</tt> @ a synchronous queue because an element are only * present if you try to remove It You cannot insert a element * (using any method) unless another thread was trying to remove it;  * You cannot iterate as there are nothing to iterate. The * <em>head</em> of the queue is the element, the first queued * inserting thread is trying to add to T He queue;  If there is no such * queued thread then no element was available for removal and * <tt>poll () </tt> would return  <tt>null</tt>. For purposes of other * <tt>Collection</tt> methods (for example <tt>contains</tt>), A * <tt&gt ;  Synchronousqueue</tt> acts as an empty collection. This queue * does not PErmit <tt>null</tt> elements. */

The characteristic of this queue is that it is empty, and it has to be blocked by the thread to get the object from the inside, so that it can be inserted into the object. What happens if a thread pool is implemented with such a queue? Or the way to get the Runnable object from the queue: (the method is public, regardless of the queue passed in)

Runnable Gettask () { for (;;) {            Try {                intState =runstate; if(State >SHUTDOWN)return NULL;                Runnable R; if(state = = SHUTDOWN)//Help Drain QueueR =Workqueue.poll ();//2, return now.Else if(Poolsize > Corepoolsize | |allowcorethreadtimeout) R=Workqueue.poll (KeepAliveTime, timeunit.nanoseconds);//wait until a certain time, do not give upElseR=Workqueue.take ();//3, blockedif(r! =NULL)                    returnR; if(Workercanexit ()) {if(Runstate >= SHUTDOWN)//Wake up Othersinterruptidleworkers (); return NULL; }                //Else Retry}Catch(Interruptedexception IE) {//On interruption, re-check runstate            }        }    }

In fact, for incoming synchronousqueue, only the blocked take () will eventually be called, and Null will always be returned for Call poll (), because the queue does not save the object. That new Cachedthreadpool () will return a thread pool that, if the number of threads is sufficient, the currently existing thread will be reused (because take () waits for a new thread), and if the current thread does not execute it, it will be new. However, this new thread will not be actively destroyed.

In addition to the following advantages, I think the code clarity is also a big advantage in that the author uses Reentrantlock, a lock to manipulate the main object, to achieve synchronization of resource access:

 final  reentrantlock mainlock = this         .mainlock;        Mainlock.lock ();  try   { if  (Poolsize < corepoolsize && runstate == RUNNING) T = Addthread (firsttask);         finally   {Mainlock.unlock ();  synchronized   (LockObject) {if  (Poolsize < corepoolsize && runstate == RUNNING) T  = Addthread (firsttask);} 

Clearly the first one is semantically more intuitive:-D

Threadpoolexecutor Source Learning (1)--Main ideas

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.