Java并发Concurrent包——ThreadPoolExecutor线程池源码分析

ThreadPoolExecutor 就是常用的线程池,下面通过其中重要的源码来分析:

线程池的状态

由下边的源码,可以得知,线程池由一个32位的 int 型来表示状态。其中高位的 3 位代表 5 种状态,低位的 29 位代表工作线程的数量。

    private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
    private static final int COUNT_BITS = Integer.SIZE - 3;    // 29
    private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

    // 线程池对应的5种状态
    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;

    // Packing and unpacking ctl
    private static int runStateOf(int c)     { return c & ~CAPACITY; }
    private static int workerCountOf(int c)  { return c & CAPACITY; }
    private static int ctlOf(int rs, int wc) { return rs | wc; }

线程池总共有 5 种状态:
- RUNNING:高 3 位为 111,表示线程池能够接受新任务,以及对新添加的任务进行处理。
- SHUTDOWN: 高 3 位为 000,表示线程池不可以接受新任务,但是可以对已添加的任务进行处理。
- STOP:高 3 位为 001,线程池不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。
- TIDYING:高 3 位为 010,所有的任务已终止,ctl 记录的任务数量为0,线程池会变为此状态,然后将执行 terminated() 函数。
- TERMINATED:高 3 位为 011,线程池彻底终止的状态。

关于这些状态的转换,文档中也很详细:

     * RUNNING -> SHUTDOWN
     *    shutdown()函数调用的时候
     * (RUNNING or SHUTDOWN) -> STOP
     *    shutdownNow()函数调用的时候
     * SHUTDOWN -> TIDYING
     *    队列和线程池都为空的时候
     * STOP -> TIDYING
     *    当线程池为空的时候
     * TIDYING -> TERMINATED
     *    terminated()函数执行完

线程池的属性

    /* 线程池中最少要保证的线程数量,这些将一直存活,除非设置了核心线程超时的参数
     * 初始时每提交一个任务,就会新建一个线程来处理,直到达到这个设定值
     * 另外,prestartAllCoreThreads()方法会直接初始化所有线程,等待接受任务
     */
    private volatile int corePoolSize;

    /* 线程池中允许的最大线程数。线程池的阻塞队列满了之后,如果还有任务提交,如果当前的线程数小于maximumPoolSize,则会新建线程来执行任务。*/
    private volatile int maximumPoolSize;

    // 空闲线程存活的时间。那些多出基本线程之外创建的线程,在超出这个时间后会被销毁
    private volatile long keepAliveTime;

    // 保存等待执行的任务的阻塞队列,BlockingQueue接口的实现类均可
    private final BlockingQueue<Runnable> workQueue;

    // 提供创建线程的功能的线程工厂
    private volatile ThreadFactory threadFactory;

    // 如果线程池饱和,队列也饱和,采取拒绝策略(或者shutdown()的情况)
    private volatile RejectedExecutionHandler handler;

ThreadFactory

其中线程工厂 ThreadFactory 可以通过 Executors.defaultThreadFactory() 来构建。

    public static ThreadFactory defaultThreadFactory() {
        return new DefaultThreadFactory();
    }

而 DefaultThreadFactory 这个默认线程工厂源码:

    static class DefaultThreadFactory implements ThreadFactory {
        private static final AtomicInteger poolNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        DefaultThreadFactory() {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() :
                                  Thread.currentThread().getThreadGroup();
            namePrefix = "pool-" +
                          poolNumber.getAndIncrement() +
                         "-thread-";
        }

        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r,
                                  namePrefix + threadNumber.getAndIncrement(),
                                  0);
            if (t.isDaemon())
                t.setDaemon(false);
            if (t.getPriority() != Thread.NORM_PRIORITY)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }

默认线程工厂,通过 newThread 方法新建线程,是非 deamon 而且优先级是 NORM_PRIORITY 的线程。

RejectedExecutionHandler

关于拒绝策略,线程池中提供了4种:
- CallerRunsPolicy 直接在调用者线程中执行
- AbortPolicy 直接抛出异常
- DiscardPolicy 直接丢掉任务
- DiscardOldestPolicy 丢弃队列中等待最久的任务,执行当前任务
实现该接口可以自定义拒绝策略。
在类中:

    private static final RejectedExecutionHandler defaultHandler =
        new AbortPolicy();

我们可以看到线程池采用的策略是 直接抛出异常的 AbortPolicy 。

构造函数

    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;
    }

线程池的创建

线程池的工具 Executors 类,已经实现了常用的几种线程池,通过上边构造函数传入不同的参数,达到几种不同效果的线程池。几种线程池都可以传入线程工厂类,这里分析最简单的创建,即采用默认线程工厂的方法。

FixedThreadPool

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

固定可用线程数量的线程池,根据参数可以看到,采用的基本数量和最大数量一样,也就是基本线程满了之后,如果队列中还有任务,只能等待线程的空闲,而不能再增加线程数量。超时时间设置为 0 ,其实也是无效的,因为没有多的线程,而基本线程即使出现空闲也不会被销毁。

SingleThreadExecutor

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

通过参数可以看出,是只有单个工作线程的线程池。

CachedThreadPool

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

通过参数可以看出,基本线程数为 0,最大数量为最大整数,空闲线程存活时间 60 秒,而且采用了 SynchronousQueue这个不存储元素的队列,每个生产操作要等待消费操作才能存入。
所以,当线程执行任务的速度赶不上任务提交的速度时,就会不断的创建线程来执行对应的任务。可能会耗尽 CPU 和 内存资源。

execute方法

    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);
    }

根据文档注释,三种情况:
1. 如果当前基本线程数不够,那么就启动新的线程来执行任务,这个任务就是其第一个任务了。然后调用 addWorker 方法,执行成功返回。
2. 如果情况 1 不满足,说明要加入阻塞队列了,这里需要进行二次验证,确保能够执行新任务。(二次验证是由于当前存在的线程被销毁,或者方法执行中线程池进入 shutdown 状态,所以可能的话还要回退。)
3. 如果情况 2 不满足,即不能加入阻塞队列或不是 RUNNING 状态,则尝试创建新线程直到 maxPoolSize,如果失败,则执行拒绝策略。

addWorker方法

addWorker 方法进行了工作线程的增加和启动。

    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 &&
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false;

            for (;;) {
                // 线程数量
                int wc = workerCountOf(c);
                // 线程数量大于最大容量返回false
                // core是给定参数,如果为true,和基本数量比较,大于基本数量返回false;
                // 如果为false,和最大数量比较,比最大数量大,返回false
                if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
                // CAS操作成功的话,让工作线程数量加1,跳出外层循环
                if (compareAndIncrementWorkerCount(c))
                    break retry;
                // CAS操作失败,获取当前状态c
                c = ctl.get();  // Re-read ctl
                // 如果当前线程池状态和之前的不同了,去外层循环重新执行
                if (runStateOf(c) != rs)
                    continue retry;
                // else CAS failed due to workerCount change; retry inner loop
                // 而如果是工作线程数量变化导致的CAS失败,直接内层继续循环即可
            }
        }

        boolean workerStarted = false;
        boolean workerAdded = false;
        Worker w = null;
        try {
            // 新建线程
            w = new Worker(firstTask);
            final Thread t = w.thread;
            if (t != null) {
                // 加锁
                final ReentrantLock mainLock = this.mainLock;
                mainLock.lock();
                try {
                    // 线程状态
                    int rs = runStateOf(ctl.get());

                    // 处于RUNNING状态或者线程池处于SHUTDOWN状态,且firstTask == null
                    if (rs < SHUTDOWN ||
                        (rs == SHUTDOWN && firstTask == null)) {
                        // 如果当前线程已经启动,抛出异常
                        if (t.isAlive()) // precheck that t is startable
                            throw new IllegalThreadStateException();
                        // 加入集合workers
                        workers.add(w);
                        // 设置最大池大小
                        int s = workers.size();
                        if (s > largestPoolSize)
                            largestPoolSize = s;
                        // 增加了worker
                        workerAdded = true;
                    }
                } finally {
                    mainLock.unlock();
                }
                if (workerAdded) {
                    t.start();
                    // 线程成功启动了
                    workerStarted = true;
                }
            }
        } finally {
            if (! workerStarted)
                addWorkerFailed(w);
        }
        return workerStarted;
    }

Worker

Worker其实就是一直在不停的接任务,执行任务,完成任务,再接任务的循环的工作线程。Woker 继承于 AQS,实现 Runnable 接口,所以 Worker 是一个带有锁的可执行的任务。Worker 的 run 方法,内部调用线程池的 runWorker 方法。

    private final class Worker
        extends AbstractQueuedSynchronizer
        implements Runnable
    {
        private static final long serialVersionUID = 6138294804551838833L;

        // 任务的thread
        final Thread thread;
        // 运行的任务
        Runnable firstTask;
        // 已经完成的任务数量
        volatile long completedTasks;

        // 构造函数
        Worker(Runnable firstTask) {
            setState(-1); 
            this.firstTask = firstTask;
            // 利用默认线程工厂来新建线程
            this.thread = getThreadFactory().newThread(this);
        }

        // 执行的run方法,调用线程池的runWorker方法
        public void run() {
            runWorker(this);
        }

        // 状态0代表未加锁,1代表加锁
        protected boolean isHeldExclusively() {
            return getState() != 0;
        }

        // 当前线程获取worker的锁
        protected boolean tryAcquire(int unused) {
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        // 释放锁
        protected boolean tryRelease(int unused) {
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        public void lock()        { acquire(1); }
        public boolean tryLock()  { return tryAcquire(1); }
        public void unlock()      { release(1); }
        public boolean isLocked() { return isHeldExclusively(); }

        void interruptIfStarted() {
            Thread t;
            if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
                try {
                    t.interrupt();
                } catch (SecurityException ignore) {
                }
            }
        }
    }

runWorker方法

    final void runWorker(Worker w) {
        // 当前线程
        Thread wt = Thread.currentThread();
        // 执行的任务
        Runnable task = w.firstTask;
        w.firstTask = null;
        // 释放锁
        w.unlock(); // allow interrupts
        boolean completedAbruptly = true;
        try {
            while (task != null || (task = getTask()) != null) {
                // worker获取锁
                w.lock();
                if ((runStateAtLeast(ctl.get(), 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;
                    // 任务完成数加1
                    w.completedTasks++;
                    // 释放锁
                    w.unlock();
                }
            }
            completedAbruptly = false;
        } finally {
            processWorkerExit(w, completedAbruptly);
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值