那些年向前冲|Java线程池深度揭秘( 三 )
仔细去看上面的代码 , 注释已经很清晰啦 。重点关注 ctl 变量 , 这个变量将线程池自身状态和线程数量 , 融合在这一个变量中 , 其中高 3 位表示线程池状态 , 低 29 位表示线程池中的线程数量 , 这样在多线程环境下更易保证线程池自身状态和线程数量的统一 , 不得不佩服源代码作者 Doug Lea , 可谓是设计甚妙!
源码解读:任务提交 submit 方法背后疑问?当调用 submit() 方法 , 把一个任务提交给线程池去处理的时候 , 线程池的处理过程是什么样的呢?
通过开篇对 Executor 的家族简介 , 能够看到 submit() 方法最终会调用 ThreadPoolExecutor 的 execute 方法 , 走进源码好好看看 execute 方法都做了啥?
重点关注源码中的注释(红框圈住部分) , 若看懂注释 , 提交任务时线程池对应的处理 , 也就懂了一半啦(感触:好的编码规范真的好重要 , 业务开发时 , 核心代码一定要有注释) 。
若依然很懵逼 , 一图胜千言 , 那就继续上图吧 。
了解上图的整体流程 , 再去看看源码就彻悟啦 。
public void execute(Runnable command) {//【Step 0. 如果任务为空则抛出 NPE 异常】if (command == null)throw new NullPointerException();int c = ctl.get();//【Step 1. 判断核心线程是否已满】// 1.1. 判断当前线程数是否已经达到核心线程数的限制if (workerCountOf(c) < corePoolSize) {// 1.2. 如果未达到核心线程数的限制 , 则会直接添加一个核心线程 , 并指定首次执行的任务 , 进行任务处理if (addWorker(command, true))return;// 1.3. 如果添加失败 , 则刷新线程池的状态和线程的数量对应的变量 ctlc = ctl.get();}//【Step 2. 判断阻塞队列是否已满】// 2.1. 检查线程池是否是运行状态 , 然后将任务添加到等待队列if (isRunning(c)// 2.3. 添加任务到等待队列成功后 , 如果线程池不是运行状态 , 则将刚添加的任务从队列移除并执行拒绝策略if (! isRunning(recheck)// 2.4. 判断当前线程数量 , 如果线程数量为 0 , 则添加一个非核心线程 , 并且不指定首次执行任务else if (workerCountOf(recheck) == 0)addWorker(null, false);}//【Step 3. 判断最大线程数量是否已经达到】// 3.1. 添加非核心线程 , 指定首次执行任务 , 如果添加失败 , 执行异常策略else if (!addWorker(command, false))reject(command);}结合注释去读代码 , 应该都能搞懂 。 很显然 execute 方法中 , 多处都调用了 addWorker 方法 , 接下来简单剖析一下 addWorker 方法 。
private boolean addWorker(Runnable firstTask, boolean core) {retry:for (;;) {int c = ctl.get();// ... ...for (;;) {// ... ...// 通过 CAS 自旋 , 增加线程数 +1 , 增加成功跳出双层循环 , 继续往下执行if (compareAndIncrementWorkerCount(c))break retry;// ... ...}}// 到这儿 , 说明已经成功的将线程数 +1 了 , 但是真正的线程还没有被添加boolean workerStarted = false;boolean workerAdded = false;Worker w = null;try {// 添加线程 , Worker 是继承了 AQS , 实现了 Runnable 接口的包装类w = new Worker(firstTask);final Thread t = w.thread;if (t != null) {final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {// ... ...// 添加新增的 Workerworkers.add(w);int s = workers.size();if (s > largestPoolSize)largestPoolSize = s;workerAdded = true;// ... ...} finally {mainLock.unlock();}if (workerAdded) {// 启动 Workert.start();workerStarted = true;}}} finally {if (! workerStarted)addWorkerFailed(w);}return workerStarted;}
推荐阅读
- 小机灵鬼|干货速来!透彻剖析微服务架构设计模式,深入开发Java有奇效
- 罗云熙|盘点那些古装帅,现代装却很“丑”的3位男神,罗云熙任嘉伦上榜
- 大众报业·海报新闻|盘点那些低价转让的公司,长城宽带100万元打包转让
- Java|计算机专业的本科生,该选择学习Java技术体系还是.NET技术体系
- 【】长城宽带100万元打包转让 盘点那些低价转让的公司
- 时尚广州|T恤的标语你了解过吗?揭秘衣服上那些奇怪的字句
- 刘药师话用药|有一种健康和美丽,从脚下开始,足部护理那些事儿
- 穿搭日记|那些一眼就让人爱上的明星耳环,便宜的才几百,陈小纭金晨都在戴
- 穿搭|那些乘风破浪的姐姐们,为什么每次都能把职业装穿得美出圈?
- 穿搭■为什么气质上总是输一大截?来看看那些教科书式的穿搭吧,学起来
