ThreadPoolExecutor线程池源码解析

在这里插入图片描述
在线程池中 如下二进制状态, 默认是RUNNING 高3位 保留 线程池状态,低29位保留线程池中 线程的数量
11 10000 00000 00000 00000 00000 00000 (-1<<29) RUNNING
00 00000 00000 00000 00000 00000 00000 SHUTDOWN
00 10000 00000 00000 00000 00000 00000 STOP
01 00000 00000 00000 00000 00000 00000 TIDYING
01 10000 00000 00000 00000 00000 00000 TERMINATED

在获取
获取 state 毫无疑问 & (1<<29)-1 那么就可以得到 高3位 反之 获取线程池个数
那么就 & ~ ((1<<29)-1 ) 取反即可 高位1 低位0

public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        // 首先获取 state [在源码中 状态和线程个数的10进制表示数 统称state]
        int c = ctl.get();
        // 当线程数 < 核心线程数 那么就通过addWoker方法来创建一个核心线程去执行任务 
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            // 如果核心线程池已满 那么再次获取状态    
            c = ctl.get();
        }
        // 如果状态为RUNNING 那么添加到 阻塞队列之中 [这个方法是 直接返回的offer]
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            // 如果状态不为RUNNING了 因为在 上面的判断是有可能线程切换的
            // 所以这儿添加进去后有可能 状态已经发生改变 所以得remove 任务
            // 如果删除失败 代表已经被执行了 那么就不管了 如果删除成功那么 使用默认的handle 来执行任务
            if (! isRunning(recheck) && remove(command))
                reject(command);
            // 如果添加后 线程数量 =0 那么新建一个线程 来执行任务 因为
            // 有可能 设置了 accessCoreThreadTimed = true 是情况 所以 线程池中是有可能没有线程的    
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        // 添加阻塞队列失败 那么 fasle 看看 线程池最大线程数量是否 已经达到 没有则执行
        // 否则 交给Handle 处理
        else if (!addWorker(command, false))
            reject(command);
    }
private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);

            // 只有当 线程池状态 =running  或者 shotdown 并且 blockQueue Not empty 的时候
            // 如果 线程池总线程 < coreThreadCount 那么就会 调用这个方法 firstTask 就是=null的
			
			// 也就是说 如果状态为 >= shotdown 你是不能继续调用 excute 方法在提交任务执行的
			// 但是允许线程池自己 在为了加速 task任务执行的速度 来创建新的线程 执行已有的任务的
            if (rs >= SHUTDOWN &&
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false;

			// cas 自旋  来增加线程的数量 ++state 因为下面 会 new Woker() 了
            for (;;) {
                int wc = workerCountOf(c);
                if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
                if (compareAndIncrementWorkerCount(c))
                    break retry;
                c = ctl.get();  
                if (runStateOf(c) != rs)
                    continue retry;
            }
        }

        boolean workerStarted = false;
        boolean workerAdded = false;
        Worker w = null;
        try {
        	// Woker 在线程池中 对线程的 封装 而Woker对应的线程 是使用默认的 线程工程 new Thread()赋值的
            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 或者 shotdown 的情况 加速task的执行所调用的 addWoker()方法
                    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();
                } 
                // 把woker放入set集合中后 启动线程
                if (workerAdded) {
                    t.start();
                    workerStarted = true;
                }
            }
        } finally {
            if (! workerStarted)
                addWorkerFailed(w);
        }
        return workerStarted;
    }
// 如上线程 .run 方法实际上 执行的就是 ThreadPoolExecutor中的这个方法 
// 每一个Woker 都有自己的 锁  Woker 实现了aqs ,有自己的同步队列 自己实现的 是不可重入锁
// tryLock() 表示的是非公平锁 Lock()反之
final void runWorker(Worker w) {
        Thread wt = Thread.currentThread();
        Runnable task = w.firstTask;
        w.firstTask = null;
        w.unlock(); 
        boolean completedAbruptly = true;
        try {
        	// 首先执行 提交进来的任务 然后 从 阻塞队列中 获取Task 任务
            while (task != null || (task = getTask()) != null) {
                w.lock();
   
                
              
                // 我的理解是 一般在业务中调用 SHUTDOWN NOW 方法 一般是出现了某种 紧急情况 让后续的任务不在
                // 被执行 , 老爷子 应该是想的是 有可能 程序员们会在 task.run 方法中来做了中断判断?
                // 因为 这儿即使不管做不做这个判断 这个任务都要执行 而且 下次getTask 必定返回null
                // 如果为STOP的情况下 尽可能最大化让 调用 api后续的任务最大话的中断执行
                // 因为 调用API 设置 线程池状态为STOP 后遍历 Wokers 需要一定的时间
                
				// 为什么没有SHUTDOWN呢 因为这个情况本来就要把任务执行完 所以除了STOP状态 都要清空中断状态
				// 让任务最大可能执行下去
                
                // 为什么会有这个想法呢因为后面再次 getTask的时候 如果为 shotdown 任务为空 STOP 自然也 	
                //	retrun null 退出了 where循环了
                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;
                    w.completedTasks++;
                    w.unlock();
                }
            }
            // 判断是否出现异常 没出现异常的情况下  走出循环会 自动 state -- 
            // 如果出现异常 会在下面这个方法 中  通过这个 布尔值 来 state --
            completedAbruptly = false;
        } finally {
            processWorkerExit(w, completedAbruptly);
        }
    }
// 获取任务 
private Runnable getTask() {
        boolean timedOut = false; // Did the last poll() time out?

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

            //如果为 stop  或者 whutdown queue is empty 那么直接 state-- 退出循环
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                decrementWorkerCount();
                return null;
            }

            int wc = workerCountOf(c);

        
            // 如果 没有任务执行了 而且 线程数量大于核心线程池  那么就把对应的线程 销毁掉
            // keepAliveTimed 就是 当没有任务执行 之后 大于核心线程池的 线程 的最大存活时间
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

            if ((wc > maximumPoolSize || (timed && timedOut))
                && (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;
            } catch (InterruptedException retry) {
            // 这儿 主要是有可能 核心线程池 一直在 获取任务时 处于watting状态
            // 那么调用 shutdown / now 后将线程唤醒后 退出的一种方式
                timedOut = false;
            }
        }
    }
// 线程 走出where 循环做 后续处理 主要是 做状态转变 shutdown stop 转为 TIDYING ---》TERMINATED做一些判断
private void processWorkerExit(Worker w, boolean completedAbruptly) {
        if (completedAbruptly) // 出现异常的情况做 state--
            decrementWorkerCount();

		//使用全局锁 对 总任务执行数 做 统计
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            completedTaskCount += w.completedTasks;
            workers.remove(w);
        } finally {
            mainLock.unlock();
        }

		// 更新状态 因为如果是 最后一个线程退出 那么为 STOP SHUTDOWN queue isempty的情况下就可以转为
		// 后续状态了 
        tryTerminate();

        int c = ctl.get();
        // 这儿是为了防止 shutdown 和 running 设置了 核心线程 允许超时的情况下
        // 会出现还有任务 但是没有线程执行的情况 做的一些处理 因为当 最后一个线程退出后 刚好 线程切换
        // 到 execute 方法 的 offer 方法射进去一个task 所以 那个地方会做一个判断这个地方 也做一个判断
        // 那个判断就是防止这个判断不起作用的判断  因为有可能这个方法执行完 才 offer也不一定
        if (runStateLessThan(c, STOP)) {
            if (!completedAbruptly) {
                int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
                if (min == 0 && ! workQueue.isEmpty())
                    min = 1;
                if (workerCountOf(c) >= min)
                    return; 
            }
            addWorker(null, false);
        }
    }
// 尝试将 线程池状态 改变成 最后2个状态
 final void tryTerminate() {
        for (;;) {
            int c = ctl.get();
            // 是running 或者 shutdown 但是任务没执行完 滚回去执行任务 
            if (isRunning(c) ||
                runStateAtLeast(c, TIDYING) ||
                (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
                return;

			//  这儿 是加速 线程的中断 类似 读写锁中 共享Node 释放锁 和拿到锁 的 暴风式的 唤醒后续的 Node
			// 是一个理 ,之所以只 唤醒一个 是优化,因为避免 轮训完所有set 中的woker浪费太多时间
			
			// 做这个判断 主要是唤醒 核心线程 之前可能阻塞在 阻塞队列处于 watting状态下 
            if (workerCountOf(c) != 0) { // Eligible to terminate
                interruptIdleWorkers(ONLY_ONE);
                return;
            }

            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
            	// 以上条件都满足 直接改变状态 如果cas失败 那么其他线程已经改了 那么不在尝试 调用一个方法后
            	// 转为 最后一个状态 这儿是一个扩展 spring中 这种东西也非常的多.
                if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
                    try {
                        terminated();
                    } finally {
                        ctl.set(ctlOf(TERMINATED, 0));
                        termination.signalAll();
                    }
                    return;
                }
            } finally {
                mainLock.unlock();
            }
            // else retry on failed CAS
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值