Java ThreadPoolExecutor 源码解读

238 阅读2分钟

ThreadPoolExecutor 简介

ThreadPoolExecutor 顾名思义 -- 线程池,通过池化技术能够有效的降低系统资源的消耗,避免频繁的创建线程,同时也能够便于我们管理这些线程,提高系统响应速度(不用创建线程)。

先从它的构造函数说起

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

可以看到一共有 7 个参数,分别是 corePoolSize(核心线程数)、maximumPoolSize(最大线程数)、keepAliveTime(存活时间)、unit(时间的那位)、workQueue(工作队列)、threadFactory(线程工厂)、handler(拒绝策略)

接着我们看一下 ThreadPoolExecutor 中的 execute 方法:

    public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        // 这里的 ctl 是一个 AtomicInteger 类型的数字
        // 其高3位用于表示线程池状态,剩下的29位用于表示线程数量
        int c = ctl.get();
        // 计算线程是否达到 corePoolSize
        // 注意此时就算线程池里有空闲的核心线程也会选择创建新的线程去执行
        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);
    }

接下来我看再看下 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
                // 如果创建的是非核心线程,则判断是否超过最大线程数,超过返回 false
                if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
                // 原子的线程数量 +1
                if (compareAndIncrementWorkerCount(c))
                    break retry;
                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 {
            // 创建 worker
            w = new Worker(firstTask);
            final Thread t = w.thread;
            if (t != null) {
                final ReentrantLock mainLock = this.mainLock;
                // 获取锁,同步的将 worker 到 workers 集合中
                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();
                    workerStarted = true;
                }
            }
        } finally {
            if (! workerStarted)
                // 同步的减少修改线程池状态并且worker数量递减
                addWorkerFailed(w);
        }
        return workerStarted;
    }

如果说最大线程添加线程失败并且队列也已经满了没有任何的空闲队列,那么就会执行 reject 方法,该方法会根据定义线程池时提供的拒绝策略来执行不同的方法

    final void reject(Runnable command) {
        handler.rejectedExecution(command, this);
    }

ThreadPoolExecutor 提供了 4 种拒绝策略供我们适用,分别是:

CallerRunsPolicy

    public static class CallerRunsPolicy implements RejectedExecutionHandler {
        
        public CallerRunsPolicy() { }

        /**
         * 如果线程池没有被关闭,那么由调用者执行该任务
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                r.run();
            }
        }
    }

AbortPolicy

public static class AbortPolicy implements RejectedExecutionHandler {
        
        public AbortPolicy() { }

        /**
         * 直接抛出异常
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }
    }

DiscardPolicy

public static class DiscardPolicy implements RejectedExecutionHandler {
    
        public DiscardPolicy() { }

        /**
         * 不做任何的处理
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        }
    }

DiscardOldestPolicy

public static class DiscardOldestPolicy implements RejectedExecutionHandler {
    
        public DiscardOldestPolicy() { }

        /**
         * 将存在 queue 队列里面时间最久的任务丢弃,然后重新尝试 execute
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }
        }
    }

如果以上 4 种拒绝策略都不满足需求,则可以通过实现 RejectedExecutionHandler 接口来自定义拒绝策略