ThreadPoolExecutor源码详解一

ThreadPoolExecutor源码详解一

ThreadPoolExecutor参数列表

  1. corePoolSize:核心线程数,除非设置了allowCoreThreadTimeOut,否则核心线程数是保持活动的最小数量0。
  2. maximumPoolSize:线程池中允许的最大线程数量
  3. keepAliveTime:空闲线程等待工作的超时时间(以纳秒为单位)。
  4. unit:TimeUnit类型,时间单位
  5. workQueue:在执行任务之前用于保留任务的队列,此队列将仅保存execute方法提交的Runnable任务。
  6. threadFactory:执行程序创建新线程时要使用的工厂
  7. handler:当达到线程边界和队列容量阻止执行时使用的处理程序

ThreadPoolExecutor的5种状态

  1. RUNNING:接收新任务和进程队列任务。
  2. SHUTDOWN:不接受新任务,但是接收进程队列任务。
  3. STOP:不接受新任务也不接受进程队列任务,并且打断正在进行中的任务。
  4. TIDYING:所有任务终止,待处理任务数量为0,线程转换为TIDYING,将会执行terminated钩子函数。
  5. TERMINATED: terminated()执行完成。

状态之间的转换:

  1. RUNNING -> SHUTDOWN:调用shutdown()方法
  2. (RUNNING or SHUTDOWN) ->STOP:调用shutdownNow()方法
  3. SHUTDOWN -> TIDYING:队列和线程池都是空的
  4. STOP ->TIDYING:线程池为空
  5. TIDYING -> TERMINATED:钩子函数terminated()执行完成

4种丢弃策略:

  1. CallerRunsPolicy:调用execute()方法拒绝任务,由向线程池提交任务的线程来执行该任务
  2. AbortPolicy: 抛RejectedExecutionException异常(默认的处理方式)
  3. DiscardPolicy:悄悄地丢弃拒绝的任务
  4. DiscardOldestPolicy:丢弃最老的未处理的请求,然后重新执行execute()方法

execute方法源码解析

public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        //获取任务状态
        int c = ctl.get();
        //(c & CAPACITY),最大就是核心线程数
        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);
            //如果任务数等于0,说明执行任务列表为空,创建一个空任务
            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);
            // 仅在必要时检查队列是否为空.
            if (rs >= SHUTDOWN &&       //线程不是运行状态
                ! (rs == SHUTDOWN &&    //取反(线程是停止状态,且不是第一个线程 且 任务队列中不是空)
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false;

            for (;;) {
                //线程
                int wc = workerCountOf(c);
                //超出容量 或大于最大线程数
                if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
                //cas增加线程个数,同时只有一个线程成功
                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 {
            w = new Worker(firstTask);
            final Thread t = w.thread;
            if (t != null) {
                final ReentrantLock mainLock = this.mainLock;
                mainLock.lock();
                try {
                    // 保持锁定时重新检查.
                    // 在 ThreadFactory 失败或在获取锁之前关闭时退出.
                    int rs = runStateOf(ctl.get());
                    if (rs < SHUTDOWN ||
                        (rs == SHUTDOWN && firstTask == null)) {
                        if (t.isAlive()) // 预先检查 t 是否可启动
                            throw new IllegalThreadStateException();
                        workers.add(w);
                        int s = workers.size();
                        //largestPoolSize是跟踪达到的最大池大小。仅在mainLock下访问
                        //我理解是当前任务数大于到达数时才会重新赋值
                        if (s > largestPoolSize)
                            largestPoolSize = s;
                        workerAdded = true;
                    }
                } finally {
                    //解锁
                    mainLock.unlock();
                }
                if (workerAdded) {
                    //启动线程
                    t.start();
                    //设置当前线程为启动
                    workerStarted = true;
                }
            }
        } finally {
            if (! workerStarted)
                //1.启动失败移出任务
                //2.减少任务数
                //3.重新检查终止,执行钩子函数terminated()
                addWorkerFailed(w);
        }
        return workerStarted;
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值