Analysis of the core method of ThreadPoolExecutor

The core of the ThreadPoolExecutor class is the Worker inner class, which consumes resources and reduces the overhead of creating threads. Worker implements the Runnable interface and inherits AbstractqueuedSynchronizer.
There is a worker HashSet inside, which stores worker threads.
The status of the thread pool: Runnable, shutdown, stop, tidying, terminated.
Its core methods:
1. executor()

    public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        /*
         * Proceed in 3 steps:
         *
         * 1. If fewer than corePoolSize threads are running, try to
         * start a new thread with the given command as its first
         * task.  The call to addWorker atomically checks runState and
         * workerCount, and so prevents false alarms that would add
         * threads when it shouldn't, by returning false.
         *
         * 2. If a task can be successfully queued, then we still need
         * to double-check whether we should have added a thread
         * (because existing ones died since last checking) or that
         * the pool shut down since entry into this method. So we
         * recheck state and if necessary roll back the enqueuing if
         * stopped, or start a new thread if there are none.
         *
         * 3. If we cannot queue task, then we try to add a new
         * thread.  If it fails, we know we are shut down or saturated
         * and so reject the task.
         */
        int c = ctl.get();     //获取线程池的线程数量
        if (workerCountOf(c) < corePoolSize) {   //如果小于核心线程数量,就新建核心线程
            if (addWorker(command, true))    //如果新建核心线程成功,就返回
                return;
            c = ctl.get();
        }
            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))
            reject(command);
    }

The above method is the execution step of adding a thread to the thread pool, in which addWorker(command, true) is called to create a thread.

//  core是指创建的线程是否是核心线程
    private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);  //获取线程池的状态

            // Check if queue empty only if necessary.
            if (rs >= SHUTDOWN &&   //如果线程池》shutdown状态或者当前task为null
                ! (rs == SHUTDOWN &&  //(running状态<shutdown)
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false;   //返回false,不创建线程

            for (;;) {  //不断循环
                int wc = workerCountOf(c);  //查看线程的数量
                if (wc >= CAPACITY ||  //如果线程数量大于容量或者根据是否是核心线程标志
                //来判断其是否超过了创建线程池规定的核心线程数量或者最大线程数量
                    wc >= (core ? corePoolSize : maximumPoolSize))//
                    return false;
                if (compareAndIncrementWorkerCount(c))  //用CAS方法增加线程池的数量
                    break retry;     // break retry后直接跳出for循环,后面的不执行,开始执行创建线程的操作
                c = ctl.get();  // Re-read ctl
                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;
        try {
            w = new Worker(firstTask); //初始化worker,此时只是新建,还没运行
            final Thread t = w.thread;
            if (t != null) {
                final ReentrantLock mainLock = this.mainLock; //获取线程池的全局锁
                mainLock.lock();
                try {
                    // Recheck while holding lock.
                    // Back out on ThreadFactory failure or if
                    // shut down before lock acquired.
                    int rs = runStateOf(ctl.get());

                    if (rs < SHUTDOWN ||
                        (rs == SHUTDOWN && firstTask == null)) {
                        if (t.isAlive()) // precheck that t is startable
                            throw new IllegalThreadStateException();
                        workers.add(w);  //将此线程添加进线程集合
                        int s = workers.size();
                        if (s > largestPoolSize)
                            largestPoolSize = s;  //跟新线程池的数量
                        workerAdded = true;
                    }
                } finally {
                    mainLock.unlock();
                }
                if (workerAdded) {
                    t.start();  //执行worker的run方法  a
                    workerStarted = true;  
                }
            }
        } finally {
            if (! workerStarted)
                addWorkerFailed(w);
        }
        return workerStarted;
    }

The worker.start() shown in a above, finally calls the run method of the wrker, and finally calls the following method

    final void runWorker(Worker w) {
        Thread wt = Thread.currentThread();
        Runnable task = w.firstTask;   //即创建线程的task
        w.firstTask = null;
        w.unlock(); // allow interrupts  这个不知道啥意思
        boolean completedAbruptly = true;
        try {
        //执行task方法或者执行完后通过getTask()获取任务队列的任务
            while (task != null || (task = getTask()) != null) {
                w.lock();
                // If pool is stopping, ensure thread is interrupted;
                // if not, ensure thread is not interrupted.  This
                // requires a recheck in second case to deal with
                // shutdownNow race while clearing interrupt
                if ((runStateAtLeast(ctl.get(), STOP) || //如果线程池处于stop
                     (Thread.interrupted() &&   //或者线程被中断
                      runStateAtLeast(ctl.get(), STOP))) &&
                    !wt.isInterrupted())
                    wt.interrupt();  //中断线程
                try {
                    beforeExecute(wt, task);  //钩子方法,待学习
                    Throwable thrown = null;
                    try {
                        task.run();  //运行
                    } 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的执行完的任务量++
                    w.unlock();
                }
            }
            completedAbruptly = false;
        } finally {
            processWorkerExit(w, completedAbruptly);  //当任务队列为空,即执行此方法
        }
    }

There are two important method calls in the above method: getTask() is to obtain tasks from the task queue, and processWorkerExit(w, completedAbruptly); is to process idle threads.

  private Runnable getTask() {
        boolean timedOut = false; // Did the last poll() time out?用于判断是否poll超时

        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);

            // Check if queue empty only if necessary.
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                decrementWorkerCount();  //如果线程池处于或大于shutdown状态并且任务队列为空
                return null;
            }

            int wc = workerCountOf(c);

            // Are workers subject to culling? timed用于标识核心线程是否超时和当前线程数是否大于核心线程数
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

            if ((wc > maximumPoolSize || (timed && timedOut)) //timeout为true且线程超过核心线程数,那就减少线程数,返回null
                && (wc > 1 || workQueue.isEmpty())) {  
                if (compareAndDecrementWorkerCount(c))
                    return null;
                continue;
            }

            try {
            //如果当前线程数大于核心线程数,那就在规定时间内从阻塞的任务队列中取任务
                Runnable r = timed ?
                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                    workQueue.take();  //如果是核心线程就一直等到
                if (r != null)
                    return r;  //取到就返回
                timedOut = true;  //取不到,置timeout为空。
            } catch (InterruptedException retry) {
                timedOut = false;
            }
        }
    }

private void processWorkerExit(Worker w, boolean completedAbruptly)用于处理空闲线程
“`
private void processWorkerExit(Worker w, boolean completedAbruptly) {
if (completedAbruptly) // If abrupt, then workerCount wasn’t adjusted
decrementWorkerCount();

    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        completedTaskCount += w.completedTasks;
        workers.remove(w);   //将w从worker删除
    } finally {
        mainLock.unlock();
    }

    tryTerminate();    //尝试终止线程池

    int c = ctl.get();   //获取线程池状态
    if (runStateLessThan(c, STOP)) {
        if (!completedAbruptly) {
            int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
            if (min == 0 && ! workQueue.isEmpty())
                min = 1;   //如果线程池核心数量为0,如果任务队列不空,那维持一个线程
            if (workerCountOf(c) >= min)
                return; // replacement not needed  //如果线程池的数量大于核心数,不操作,直接返回
        }
        addWorker(null, false);   //否则,要创建空线程
    }
}

"The
thread pool will become shutdown state after shutdown(), no new tasks will be received at this time, but the tasks that are running and waiting in the blocking queue will be processed.

After shutdownNow(), the thread pool will change to the stop state. At this time, no new tasks will be received, tasks waiting in the blocking queue will no longer be processed, and an attempt will be made to interrupt the worker threads that are being processed.
Then, look at the shutdown() method:

    public void shutdown() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();   //获取全局锁
        try {
            checkShutdownAccess();  //判断是否有权限进行shutdown操作
            advanceRunState(SHUTDOWN);  //设置线程池的状态为shutdown,不再允许进行线程的添加操作
            interruptIdleWorkers();  //中断空闲的线程
            onShutdown(); // hook for ScheduledThreadPoolExecutor
        } finally {
            mainLock.unlock();
        }
        tryTerminate();   //尝试终止线程池
    }

it will call

    private void interruptIdleWorkers(boolean onlyOne) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            for (Worker w : workers) {
                Thread t = w.thread;
                if (!t.isInterrupted() && w.tryLock()) {
                    try {
                        t.interrupt();
                    } catch (SecurityException ignore) {
                    } finally {
                        w.unlock();
                    }
                }
                if (onlyOne)
                    break;
            }
        } finally {
            mainLock.unlock();
        }
    }

interruptIdleWorkers() will first acquire the mainLock lock, because to iterate the workers set, two judgments need to be made before each worker is interrupted:

1. Whether the thread has been interrupted or not, do nothing

2. Whether worker.tryLock() is successful

The second judgment is more important, because in addition to implementing the executable Runnable, the Worker class also inherits AQS, which is itself a lock

tryLock() calls the tryAcquire() method implemented by the Worker itself, which is also the method that AQS stipulates that subclasses need to implement to try to acquire the lock.
Because the worker's lock is not reentrant, and running tasks in the runworker will update the worker Lock operation, therefore, in the above code, only idle threads will perform the t.interrupt() operation. After catching the interrupt exception, it will continue to loop to the logic of judging the thread pool state at the beginning of getTask(). When the thread pool is in the shutdown state and workQueue.isEmpty, it will return null and perform the worker thread exit logic.
tryTerminate() execution flow:

1. Determine whether the thread pool needs to enter the termination process (only when the shutdown state + workQueue.isEmpty or stop state is required)

2. Determine whether there are still threads in the thread pool. If there is, interruptIdleWorkers(ONLY_ONE) tries to interrupt an idle thread (it is this logic that can issue an interrupt signal again, interrupting the thread blocking the task acquisition)

3. If the status is SHUTDOWN, the workQueue is also empty, and there are no running workers. Start terminated.

会先上锁,将线程池置为tidying状态,之后调用需子类实现的 terminated(),最后线程池置为terminated状态,并唤醒所有等待线程池终止这个Condition的线程

And shutodwnnow directly sets the state of the thread pool to stop, and then sends an interrupt signal to all threads.

Summary:
1. There is an AtomicInteger variable inside the threadpoolExecutor to count the number and status of threads in the thread pool (higher three). Its status is running, shutdown, stop, tidying, terminated. From small to
2, there is an inner class worker inside threadpoolExecutor, which is used to create threads. The execution step is to create a thread when the number of threads is less than the number of core threads, otherwise submit the task to the task queue. If the task queue is full, check whether the number of threads is less than the maximum number of threads. If it is less, create a thread. Otherwise an exception is thrown.
3. The worker's runworker method (that is, the newly created thread) first executes the task specified by the user. After the execution is completed, it goes to the task queue to fetch the task and continue to execute. In the gettask() method of taking a task, it is necessary to judge whether the number of threads is less than the number of core threads. If it is greater, perform a poll operation on the task queue (blocked) for a specified time, and return null if not. If it is less than or equal to the number of core threads, it will always block. After returning null, the idle thread is destroyed.
4. The work of destroying idle threads is to remove the thread from the thread set and try to destroy the thread pool (in this method, the idle thread is interrupted and the thread is destroyed). In addition, if the number of threads is found to be less than the number of core threads, an empty thread is also created.
5. The shutdown() method is used to destroy the thread pool. It sets the state of the thread pool to the shutdown state, prevents the continued submission of tasks, interrupts the idle thread, and destroys the thread. For tasks in the task queue and executing, continue execution. The purpose of destroying the idle thread is to acquire the lock (at this time, the working thread lock cannot be acquired by it if it is not released), and then call its interrupt method. For the core thread that is blocking the acquisition task, it is interrupted in tryTerminate().
6. shutdownnow() is to set the state of the thread pool to stop, perform the interrupt() operation on all threads, and return the unexecuted tasks as a list.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325901012&siteId=291194637