Java 多线程线程池-ThreadPoolExecutor的Worker类对象分析

0.Worker类对象的类图

Java 多线程线程池-ThreadPoolExecutor的Worker类对象分析_第1张图片

1.Worker类对象的解释

线程池中的线程,都会被封装成一个Worker类对象,ThreadPoolExecutor维护的其实就是一组Worker对象;

Worker类中有两个属性,一个是firstTask,用来保存传入线程池中的任务,一个是thread,是在构造Worker对象

的时候,利用ThreadFactory来创建的线程,用来处理任务的线程;

Worker继承AQS,使用AQS实现独占锁,并且是不可重入的,

构造Worker对象的时候,会把锁资源状态设置成-1,因为新增的线程,还没有处理过任务,是不允许被中断的

2.Worker实现接口Runnable,执行run方法

//向线程池中添加线程成功,并且启动也成功,则执行Worker对象的run方法,进入runWorker方法逻辑
    final void runWorker(ThreadPoolExecutor.Worker w) {
        Thread wt = Thread.currentThread();
        //在构造Worker对象的时候,会把一个任务添加进Worker对象
        //因此需要把其作为新增线程的第一个任务来执行
        Runnable task = w.firstTask;
        //已经将该任务拿出来进行执行,则需要将该worker对象即线程池中的线程对象
        //持有的任务清空
        w.firstTask = null;
        //将AQS锁资源的状态有-1变成0,运行该线程进行中断
        w.unlock();
        //用来判断执行任务的过程中,是否出现了异常
        boolean completedAbruptly = true;
        try {
            //线程池中的线程循环处理线程池中的任务,知道线程池中的任务被处理完
            //跳出循环
            while (task != null || (task = getTask()) != null) {
                //给该线程加锁,一个线程只处理一个任务
                w.lock();
                // 线程池是否是STOP状态
                // 如果是,则确保当前线程是中断状态
                // 如果不是,则确保当前线程不是 中断状态
                if ((runStateAtLeast(ctl.get(), STOP) ||
                        (Thread.interrupted() &&
                                runStateAtLeast(ctl.get(), STOP))) &&
                        !wt.isInterrupted())
                    wt.interrupt();
                try {
                    //扩展使用,在执行任务的run方法之前执行
                    beforeExecute(wt, task);
                    Throwable thrown = null;
                    try {
                        //执行任务的run方法
                        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 {
                        //扩展使用,在执行任务的run方法之后执行
                        afterExecute(task, thrown);
                    }
                } finally {
                    task = null;
                    w.completedTasks++;
                    w.unlock();
                }
            }
            //正常执行完任务
            completedAbruptly = false;
        } finally {
            //所有的任务都处理完后,或者执行任务的过程中出现了异常
            processWorkerExit(w, completedAbruptly);
        }
    }

3.核心方法getTask


    private Runnable getTask() {
        //timedOut表示 记录上一次从队列中获取任务是否超时
        boolean timedOut = false; // Did the last poll() time out?
        //自旋
        for (;;) {
            //获取线程池的状态和线程池中线程数量组成的整形字段,32位
            // 高3位代表线程池的状态,低29位代表线程池中线程的数量
            int c = ctl.get();
            //获取高3位的值,即线程池的状态
            int rs = runStateOf(c);

            // 如果线程状态不是Running状态,并且 线程也不是SHUTDOWN状态 或者任务队列已空
            //
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                //则将线程池中的线程数量减1
                decrementWorkerCount();
                //返回一个空任务,1:如果任务队列已空,则想返回任务也没有
                //             2:如果线程池处于STOP或者之上的状态,则线程池不允许在处理任务
                return null;
            }
            //获取低29位的值,即线程池中线程的数量
            int wc = workerCountOf(c);

            // timed是否需要进行超时控制
            // allowCoreThreadTimeOut默认false
            // 当线程池中线程的数量没有达到核心线程数量时,获取任务的时候不允许超时
            // 当线程池中线程的数量超过核心线程数量时,获取任务的时候不允许超时
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
            // wc > maximumPoolSize的情况是因为可能在此方法执行阶段同时执行了setMaximumPoolSize方法;
            // timed && timedOut 如果为true,表示当前操作需要进行超时控制,并且上次从阻塞队列中获取任务发生了超时
            // 接下来判断,如果有效线程数量大于1,或者阻塞队列是空的,那么尝试将workerCount减1;
            // 如果减1失败,则返回重试
            // 如果wc == 1时,也就说明当前线程是线程池中唯一的一个线程了。
            if ((wc > maximumPoolSize || (timed && timedOut))
                    && (wc > 1 || workQueue.isEmpty())) {
                if (compareAndDecrementWorkerCount(c))
                    return null;
                continue;
            }

            try {
                //获取任务
                //如果timed = true ,则根据keepAliveTime设置的时间内,阻塞等待从队列中获取任务
                //如果timed = false,则阻塞,直到从队列中获取到任务为止
                Runnable r = timed ?
                        workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                        workQueue.take();
                //如果获取到任务,则把任务返回
                if (r != null)
                    return r;
                //执行到这里,说明在允许的时间内,没有获取到任务
                timedOut = true;
            } catch (InterruptedException retry) {
                //获取任务没有超时,但是出现异常了
                timedOut = false;
            }
        }
    }

4.核心方法processWorkerExit

    private void processWorkerExit(ThreadPoolExecutor.Worker w, boolean completedAbruptly) {
        //如果 completedAbruptly = true ,则线程执行任务的时候出现了异常,需要从线程池中减少一个线程
        //如果 completedAbruptly = false,则执行getTask方法的时候已经减1,这里无需在进行减1操作
        if (completedAbruptly)
            decrementWorkerCount();

        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            //统计该线程池完成的任务数
            completedTaskCount += w.completedTasks;
            //从线程池中移除一个工作线程
            workers.remove(w);
        } finally {
            mainLock.unlock();
        }
        //根据线程池的状态,决定是否结束该线程池
        tryTerminate();

        int c = ctl.get();
        //当线程池是RUNNING或SHUTDOWN状态时,如果worker是异常结束,那么会直接addWorker;
        //如果allowCoreThreadTimeOut=true,并且等待队列有任务,至少保留一个worker;
        //如果allowCoreThreadTimeOut=false,活跃线程数不少于corePoolSize
        if (runStateLessThan(c, STOP)) {
            if (!completedAbruptly) {
                int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
                if (min == 0 && ! workQueue.isEmpty())
                    min = 1;
                if (workerCountOf(c) >= min)
                    return; // replacement not needed
            }
            addWorker(null, false);
        }
    }

5.工作线程的生命周期

Java 多线程线程池-ThreadPoolExecutor的Worker类对象分析_第2张图片

你可能感兴趣的:(多线程)