Java and explore the principles of contract in the thread pool ThreadPoolExecutor

I. Introduction thread pool

  Use the thread pool is mainly to solve two problems: ① thread pool to provide better performance when performing a large number of asynchronous tasks, without using a thread pool time, whenever you want to perform asynchronous tasks directly to a new thread to run, then , thread creation and destruction are required overhead. The threads in the pool is reusable, each time does not need to perform asynchronous tasks to re-create and destroy threads; ② thread pool to provide a resource limitations and management tools, such as can limit the number of threads, dynamic new thread and so on.

Two, ThreadPoolExecutor class

1, we briefly look at some of ThreadPoolExecutor on member variables and the meaning it represents

   ThreadPoolExecutor AbstractExecutorService in inherited, which is a member variable of type Integer ctl atomic variable, the number of threads used to record the state of the thread pool and thread pool, similar to the previously mentioned read-write lock using a variable to hold the two kinds of information. Here (Integer seen 32) represents a three CTL high number of threads in the thread pool 29 represents the state of the thread pool, behind. It is as follows member variable in the source code ThreadPoolExecutor

1  // (three bits) indicates the state of the thread pool, (the lower 29 bits) indicates the number of threads in the thread pool;
 2  // default is the RUNNING state, the number of thread pool is 0 
. 3  Private  Final of AtomicInteger CTL = new new of AtomicInteger (ctlOf (the RUNNING, 0 ));
 . 4  
. 5  // denotes the number of threads is the number of bits remaining after -3 Integer number of bits represented by the following specific platform;
 6  // wherein Integer.SIZE = 32, the number of the lower 29 bits of the thread is represented by the following -3 
. 7  Private  static  Final  int COUNT_BITS Integer.SIZE = -. 3 ;
 . 8  
. 9  // thread maximum number (low 29) 00011111111111111111111111111111 (1 << 29-1) 
10  Private  static  Final  int= In CAPACITY (COUNT_BITS <<. 1) -. 1 ;
 . 11  
12 is  // thread pool state (high state 3 indicates the thread pool)
 13 is  // 111 00000000000000000000000000000 
14  Private  static  Final  int the RUNNING = -1 << COUNT_BITS;
 15  
16  // 000 00000000000000000000000000000 
. 17  Private  static  Final  int the SHUTDOWN = 0 << COUNT_BITS;
 18 is  
. 19  // 001 00000000000000000000000000000 
20 is  Private  static  Final  int the STOP = <<. 1 COUNT_BITS;
 21 is 
22 //010 00000000000000000000000000000
23 private static final int TIDYING    =  2 << COUNT_BITS;
24 
25 //011 00000000000000000000000000000
26 private static final int TERMINATED =  3 << COUNT_BITS;
27 
28 //获取高3位(运行状态)==> c & 11100000000000000000000000000000
29 private static int runStateOf(int c)     { return c & ~CAPACITY; }
30 
31 //Get the lower 29 bits (number of threads) ==> 00011111111111111111111111111111 & C 
32  Private  static  int workerCountOf ( int C) { return C & in CAPACITY;}
 33 is  
34 is  // calculate new values atoms ctl variable (operating state and the number of threads) 
35  Private  static  int ctlOf ( int RS, int WC) { return RS | WC;}

  Here we briefly explain the meaning of the above thread state:

  ①RUNNING: accept new tasks and processing tasks blocking queue

  ②SHUTDOWN: new task but refused to deal with the task of blocking queue

  ③STOP: new task and refused to abandon the task of blocking the queue, and it will interrupt the currently executing task

  ④TIDYING: After performing all the tasks (tasks include blocking queue) of the current number of active threads in the thread pool is zero, the method will be called terminated

  ⑥TERMINATED: termination status. State after the method call terminated

2, following a preliminary understanding about the parameters and the realization of the principle of ThreadPoolExecutor

  ①corePoolSize: the number of cars is now the core of the thread pool

  ②workQueue: Save wait for the task to perform the task of blocking queue (such as array-based bounded blocking queue ArrayBlockingQueue, based on the list of unbounded blocking queue LinkedBlockingQueue etc.)

  ③maximumPoolSize: The maximum number of threads in the thread pool

  ④ThreadFactory: Create a thread factory

  ⑤RejectedExecutionHandler: deny policy, means that when the queue is full and the number of threads in the thread pool reaches the maximum number of threads when a new task for the strategy submitted taken, there are four main strategies: AbortPolicy (thrown), CallerRunsPolicy (only the caller where the threads to run the task), DiscardOldestPolicy (losing the blocking queue recent task to handle tasks that are currently submitted), DiscardPolicy (without processing, direct discarded)

  ⑥keepAliveTime: survival time, if the current number of threads in the pool than the core number of threads, and the current thread is idle, this variable is the maximum survival time of these threads

  ⑦TimeUnit: survival time per unit time.

  According to the above parameters introduced, a brief look at implementation principles thread pool, to submit a new task as a starting point, the main processing flow analysis thread pool

3, on the use of some type of thread pool

  ①newFixedThreadPool: Create a core number of threads and the maximum number of threads are nThreads thread pool, and the queue length of the blocking Integer.MAX_VALUE, keepAliveTime = 0 as long as the number of instructions the number of threads than the core thread is currently idle and that is recovered.

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

 

  ②newSingleThreadExecutor: Create a core number of threads and the maximum number of threads the thread pool 1, the length of the queue and block Integer.MAX_VALUE, keepAliveTime = 0 as long as the number of threads than the described number of core threads and recovering the current thread is idle i.e. thread.

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}

 

   ③newCachedThreadPoolExecutor: Create a thread pool threads created on demand, the number 0 is the initial thread, up to the number of threads Integer.MAX_VALUE, synchronous queue and the queue is blocked (at most only one element), keepAliveTime = 60 demonstrates that if the current thread 60s idle is recovered. The characteristics of this type of thread pool is: Task synchronization join the queue will be executed immediately, synchronization queue can only have one task

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

 

   4, ThreadPoolExecutor the other members

  Which may refer to the previous ReentrantLock wrote lock --Lock Java and in the synchronized , which dropped to the concrete realization of the principle of ReentrantLock;

  About AQS said before the reference portion may be in Java queue synchronizer AQS , also referred to the specific implementation principle on AQS analysis;

  Knowledge about the condition of the queue may refer back to write in Java Condition thread of collaboration , which comes to the realization of the principle on Java threads Condition of collaboration;

// exclusive lock for controlling the new worker thread atomicity operation Worker 
Private  Final of ReentrantLock mainLock = new new of ReentrantLock ();

// working set of threads, Worker inherited AQS and interfaces Runnable interface, specific processing tasks thread object
 // Worker achieve AQS, and to realize his simple non-reentrant exclusive lock, where state = 0 represents the current state of the lock is not acquired , state = 1 indicates that the lock is acquired,
 // state = -1 indicates the default state Work created time, created when the state = -1 is provided to prevent the operation of the method is interrupted before runWorker 
Private  Final HashSet <the Worker> Workers = new new HashSet < the Worker> ();

// Termination condition that the corresponding lock queue, awaitTermination invoked when the thread used to store the blocked thread 
Private  Final for condition Condition mainLock.newCondition Termination = ();

Third, source code analysis

1, public void execute (Runnable command) implemented method of

  The role of executor method is to submit to the thread pool task command execution, can simply be read subject to the following figures, ThreadPoolExecutor implementation is similar to a producer-consumer model, when users add tasks to the thread pool equivalent to the producers to produce elements, workers worker directly perform tasks or obtain tasks from the task queue, equivalent to the consumption of consumer elements.

. 1  public  void Execute (the Runnable Command) {
 2      // (. 1) first checks whether the task is null, null is thrown, or performs the following steps 
. 3      IF (Command == null )
 . 4          the throw  new new a NullPointerException ();
 . 5      / (2) / CTL contains the value of the current state of thread pool and the number of threads in the thread pool 
. 6      int C = ctl.get ();
 . 7      // (. 3) workerCountOf method is to obtain the low 29, i.e., acquires the current thread pool the number of threads, is less than corePoolSize, to open a new thread to run 
. 8      IF (workerCountOf (C) < corePoolSize) {
 . 9          IF (addWorker (Command, to true ))
 10              return ;
 . 11         = C ctl.get ();
 12 is      }
 13 is      // (. 4) if the thread pool RUNNING state, the task is added to the blocking queue 
14      IF (isRunning (C) && workQueue.offer (Command)) {
 15          // ( 4-1) secondary inspection, get the value of ctl 
16          int Recheck in = ctl.get ();
 17          // (4-2) if the current thread pool is not out of the RUNNING state, delete the job from the queue, and refused to execute strategy 
18          IF (! isRunning (Recheck in) && the Remove (the Command))
 19              Reject (the Command);
 20          // (4-3) otherwise, if the thread pool is empty, add a thread 
21          the else  IF (workerCountOf (Recheck in) == 0 )
 22             addWorker ( null , false );
 23      }
 24-      // (5) If the queue is full, the new thread if the new thread fails, deny policy on the implementation of 
25      the else  IF (addWorker (the Command,! false ))
 26          Reject (the Command );
 27 }

  We look at the flow of execution of the code above, according to the analysis of digital markers:

  Step (3) determines the current number of threads in the pool is less than corePoolSize, if the number of threads less than the core, a core thread will add tasks to workers inside.

  If the current number of threads in the pool is greater than the core number of threads on the implementation (4). (4) first determines the current thread pool is in the RUNNING state, if in this state, you add tasks to the task queue, where the state is required to determine the thread pool is because the thread pool may already be in non-RUNNING state, while in the non-RUNNING state is the need to abandon the new task.

  If you want to add a task queue task is successful, the need for secondary calibration, because after adding the task to the task queue, the thread pool status may have changed, so there needs to be a secondary check, if the current thread pool is not RUNNING the state, the task needs to be removed from the task queue, and then refuse to execute strategy; if the secondary verification succeeds then execute the code again 4-3 to determine whether the current thread pool is empty, if the thread is not the thread pool is empty, then We need to create a new thread.

  If the above step (4) create added task fails, the queue is full, then (5) attempts to re-open a new thread to perform tasks (analog image above thread3 and thread4, namely those threads is not a core thread), if the current number of threads in the thread pool has been greater than the maximum number of threads maximumPoolSize, that they can not open a new thread. It belongs to the thread pool is full and the task queue is full, you need to perform denial strategy.

 

Guess you like

Origin www.cnblogs.com/fsmly/p/11007334.html