Source learn first article (thread pool)

It must have been asked during the interview over the thread pool. Why use a thread pool it? Because frequently create threads in the system will cause great CPU consumption. And run out of thread to wait for the GC recovery will cause consumption.

Here we have to learn the most common thread pool ThreadPoolExecutor,

First, take a look at its constructor:

    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long 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();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

Parameter Description:

corePoolSize: a core number of threads, the minimum number of threads in the thread pool to maintain the normal active (will not guarantee thread timeout), and 0 is not allowed, unless a timeout settings allow threads to wait (if the number is greater than the task of submitting this parameter, the task will be submitted It is placed in the buffer queue).
maximumPoolSize: maximum number of threads, is the maximum number of threads in the thread pool can hold.
keepAliveTime: idle thread survival time. When there is more than corePoolSize or set the idle timeout to allow the core thread when the thread is automatically destroyed (the default in nanoseconds) after waiting so long.
unit: the survival time of the unit thread idle.
workQueue: waiting queue, pay attention to this queue is blocked, when there is no task queue thread gets the task will be blocked until the task when there is awakened.
threadFactory: thread factory, the factory model know everything, if there is a need custom thread, implement the interface ThreadFactory return your custom thread class from newThread method just fine.
handler: deny policy processor, you can not receive new jobs when it will reject calls the method of the processor rejected out some tasks in the thread pool.

Thread pool rejection policy processing interface: RejectedExecutionHandler
implementation class:
direct denial policy (no error): DiscardPolicy
direct denial strategy (RejectedExecutionException will throw an error): AbortPolicy
let himself into the thread running task: CallerRunsPolicy
abandon the longest waiting time task: DiscardOldestPolicy

After reading these parameters are not still confused? Haha, I also like this. To understand the thread pool, one should first understand its status.

    private static final int COUNT_BITS = Integer.SIZE - 3;
    //CAPACITY 值为 1 << 29 = 0010 0000 0000 0000 0000 0000 0000 0000
    // (1 << 29) -1 = 0001 1111 1111 1111 1111 1111 1111 1111
    private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

    //线程池状态
    // -1 << 29 = 1110 0000 0000 0000 0000 0000 0000 0000
    private static final int RUNNING    = -1 << COUNT_BITS;
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    private static final int STOP       =  1 << COUNT_BITS;
    private static final int TIDYING    =  2 << COUNT_BITS;
    private static final int TERMINATED =  3 << COUNT_BITS;

Thread pool status:
the RUNNING: take 30 to 32 representative of operation 111, the new task may be received and will be processed in the queue of waiting tasks.
SHUTDOWN: Take 30-32 000 represents the close, the task being performed without interruption, but will interrupt waiting thread. Waiting task then processed remaining in the queue is closed.
STOP: Take 30-32 001 representative of stop, do not accept the new task is not the processing of waiting tasks queue. And interrupt running tasks.
TIDYING: Take 010 Representative clear rationale, the final finishing touches 30-32, close to the end of the intermediate state, all the tasks have been completed, the number of worker thread workerCount is 0, thread pool to execute the method ends.
TERMINATED: Take 30-32 011 mean the end, the end of the method is completed, ends the thread pool.
Thread pool state transitions:
the RUNNING -> SHUTDOWN: After calling shutdown () method, the thread pool will begin to refuse to accept new tasks, the transition from running in the closed state. Usually called when the thread pool to complete the work need to be destroyed.
RUNNING -> STOP: After calling shutdownNow () method, the thread pool will refuse to accept the task and thus interrupt the task being performed, transferred from the state to stop running.
SHUTDOWN -> STOP: After calling shutdownNow () method, the thread pool will refuse to accept the task and thus interrupt task is being executed, turned from a closed state to stop in.
SHUTDOWN -> TIDYING: thread pool itself is in a state of stop, queues and thread pools are empty. Thread into the clean-up state.
STOP -> TIDYING: When the thread pool is empty, clean up the state into the thread pool from a stopped state.
TIDYING -> TERMINATED: When cleanup is finished, the thread callback terminated () method, after the completion of the formal end of the thread.

These states now do not understand what to use, you can put aside, let's look at a few of the more central thread pool method. To make the code easier to understand, I joined in the above comments.

    // obtain process state, taken as the state of the counter bits 30-32 of the thread pool 
    Private  static  int runStateOf ( int C) { return C & ~ in CAPACITY;}
     // taken after counter 29 as a number of threads 
    Private  static  int workerCountOf ( int C) { return C & in CAPACITY;}


    // thread pool method of performing 
    public  void Execute (the Runnable Command) {
         IF (Command == null ) {
             the throw  new new a NullPointerException ();
        }
        // Get the value of the counter 
        int C = CTL. GET ();

        /*
         * If the number of threads running less than the core number of threads corePoolSize, started a new thread to perform this task.
         * AddWorker method will check (the total number of threads of work) runState (operating state) and workerCount atomically
         * Returns false if the operation status is closed or work in the total number of threads equal to the core number of threads.
         * / 
        // after taking workerCountOf counter 29 and compare the number of threads as the number of core threads 
        IF (workerCountOf (C) < corePoolSize) {
             // start a new thread to do the work 
            IF (addWorker (Command, to true )) {
                 return ;
            }
            // get the latest counter value 
            . C = ctl GET ();
        }
        /*
         * IsRunning running state is judged by the value of the counter obtained atoms (note if the top three operating states must be 111 throughout the minus sign),
         * If you are running status is running, you try to insert a task to the end of the waiting queue.
         * / 
        IF (isRunning (c) && workQueue.offer (the Command)) {
             // Get the latest value of the counter 
            int Recheck in = ctl. GET ();
             // determine thread pool state again, if this time the thread pool to enter other states, fold delete tasks just added, and called idle interrupt thread method remove the 
            IF (isRunning (Recheck in) &&! {remove (the Command))
                 // call rejection policy 
                reject (command);
            }
            /*
             * If the thread pool is still in operation or threads are down, but it failed to delete the task queue.
             * Determine the number of worker threads is 0, then it is free to create a thread into the pool, so that he would perform the task in the queue after
             * Clean up the state into the thread pool
             */
            else if (workerCountOf(recheck) == 0){
                addWorker(null, false);
            }
        }
        /*
         * If you are running status is closed again try to call addWorker way to run this task, then addWorker 
         * Returns false. At this time refused to execute strategies (denial strategy reject the underlying method is actually called denial method).
         * Operation, but because the queue is full, insert fails, again calling addWorker If the thread state is attempting to run
         * Task, and the method parameters core if the number of threads does not exceed the maximum number of threads will create a new thread to run the task is false
         * AddWorker method introduced below
         */
        else if (!addWorker(command, false)){
            reject(command);
        }
    }

    // method will be added to the task at work, one of the core thread pool method
     // mean parameter represents the core is not to compare the core number of threads. 
    Private Boolean addWorker (the Runnable firstTask, Boolean Core) {
        retry:
        for (;;) {
             // Get the value of the counter 
            int C = CTL. GET ();
             // Take 30 -32 thread status bit is determined 
            int RS = runStateOf (C);
             / *
             * If the thread pool is at a standstill, clean-up, the end of the state, etc., directly returns false reject the task
             * If the thread is closed in and passed the task is not empty directly reject the task.
             * If the incoming task is empty, but the queue is empty, no proof the task do not create a new thread, directly back to the end of the method.
             */
            if (rs >= SHUTDOWN && ! (rs == SHUTDOWN && firstTask == null && ! workQueue.isEmpty())){
                return false;
            }
            for (;;) {
            
                // Get the current number of threads 
                int WC = workerCountOf (c);
                 // whether the number of threads exceeds the limit the capacity of judgment, and if no more than is true in the core than the core number of threads to see if
                 // If it is false and core and maximum thread the number of comparison. If you exceed the returns false reject the task. 
                IF (WC> = || WC in CAPACITY> = (Core? corePoolSize: maximumPoolSize)) {
                     return  to false ;
                }
                // number counter thread modifies atoms not necessary if the modification is successful in an infinite loop disconnect cycles direct execution cycle not Skip outermost 
                IF (compareAndIncrementWorkerCount (C)) {
                     BREAK the retry;
                }
                // If the above is not acquired successfully modified counter value again atom 
                C = CTL. GET ();   // Re-Read CTL
                 // determines if the same modifications as the cycle continues, if not the same as the end of the loop to jump out of the current state and the previous to the outermost circle, and start again 
                IF (runStateOf (C) =! RS) {
                     Continue the retry;
                }
                // else CAS failed due to workerCount change; retry inner loop
            }
        }

        boolean workerStarted = false;
        boolean workerAdded = false;
        Worker w = null;
        try {
            w = new Worker(firstTask);
            the Thread T Final = w.thread;
             IF (! T = null ) {
                 // Get the main lock, in order to ensure the safety of adding a concurrent task 
                Final = mainLock of ReentrantLock the this .mainLock;
                mainLock. Lock ();
                 the try {
                     // . Recheck in the while Holding Lock
                     // the Back failure or a ThreadFactory IF OUT ON
                     // . Shut Down before Lock Acquired
                     // after obtaining the lock operating state of the thread pool from a new acquisition 
                    int RS = runStateOf (CTL . GET ());
                     // If the thread is running or who threads are down, but it failed to delete the task queue. And the whole thread pool thread has been interrupted 
                    IF (rs <SHUTDOWN || (rs == SHUTDOWN && firstTask == null )) {
                         // determine whether the thread is active 
                        IF (t.isAlive ()) //T IS Startable that PreCheck 
                            the throw  new new an IllegalThreadStateException ();
                         // the new work queue worker thread was added 
                        workers.add (W);
                         // Get number of worker threads 
                        int S = workers.size ();
                         IF (S> largestPoolSize)
                            largestPoolSize = S;
                         // set the working threads are successful 
                        workerAdded = to true ;
                    }
                } finally {
                    mainLock.unlock ();
                }
                // If the worker thread to join the successful launch of a new thread and the thread state is set to true 
                IF (workerAdded) {
                    t.start();
                    workerStarted = true;
                }
            }
        } finally {
            if (! workerStarted)
                addWorkerFailed(w);
        }
        return workerStarted;
    }

Here, incidentally, why not let Ali specification with Executors.newSingleThreadExecutor (); This method creates a thread pool.

We can look at his source:

    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
This is a blocking LinkedBlockingQueue infinite queue, the queue as long as that is not the OOM can always fill it up. This will result or not to continue treatment but to create a thread in the future if the number of threads to reach the core number of threads, but will have to plug the task queue until the memory overflow.

Guess you like

Origin www.cnblogs.com/Raiden-xin/p/12227458.html