关于线程池一个初步的认识

话不多说,从JUC包下的线程池源代码开始,探索学习大师的匠心独运。不过,首先我不会逐行逐句的去看源码,这样会让我今天有限的时间全部陷入进去。其实光看那详尽的注释就差不多明白一半。学习这个并不是为了成为Doug Lea那样的大神,只不过是为了搞清楚它的设计思想和运行原理,以便我们能够在合适的场景如何合适的去设计程序。
线程池是为了避免线程重复创建和销毁,统一对线程进行调控的线程管理资源池,以达到最大限度的降低系统资源的损耗。
为了在不必要的细节上浪费时间,可以事先熟悉以下状态和参数变量的定义。

//使用ctl存放两类信息,前高3位表示线程池运行状态,后29位表示线程个数
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

// 线程池的运行状态,看高3位
// 创建线程池并初始化后,线程池处于RUNNING状态
private static final int RUNNING    = -1 << COUNT_BITS;
// 线程池关闭,拒绝接受新任务,但是依旧处理阻塞队列里的任务,调用shutdown()方法会进入这一状态
private static final int SHUTDOWN   =  0 << COUNT_BITS;
// 线程池关闭,拒绝接受新任务并抛弃阻塞队列中的任务,同时中断正在处理的任务,调用shutdownNow()方法会直接进入这一状态
private static final int STOP       =  1 << COUNT_BITS;
// 所有的任务都终止,线程池进入这一状态。当线程池变为TIDYING状态,会执行钩子函数terminated(),这是一个空方法,如果你想在这个状态做些什么事情,可以重载
private static final int TIDYING    =  2 << COUNT_BITS;
// 最终状态,线程池终止变成TERMINATED
private static final int TERMINATED =  3 << COUNT_BITS;`

状态切换流程如下:
image
线程池的核心参数:
corePoolSize:线程池核心线程数;
workQueue:等待执行的任务阻塞队列
maximumPoolSize:线程池最大线程数,有人称为救急线程
ThreadFactory:创建线程的工厂
keeyAliveTime:存活时间。如果当前线程池的线程数比核心线程数多,并且是闲置状态,这些闲置的线程能存活的最大时间。
TimeUnit,存活时间的时间单位
RejectedExecutionHandler:当队列满且线程数达到 maximumPoolSize 后执行的拒绝策略。
RejectedExecutionHandler defaultHandler = new AbortPolicy();默认抛出异常

以上状态和参数先标记一下,以下简单的看看吧。放大格局就三步(所以姿势水平不够,但格局要大),中文注释都是照着原文机翻。说人话就是:
1)判断当前运行的线程数小于corePoolSize,就创建一个带着任务的核心线程并启动。
2)如果创建不了线程,就尝试offer到阻塞队列中去。这里要做两个判断,线程池状态是否还是运行状态,不是就要把加到队列中的任务吐出来。还有一个判断线程数是否是0,是的话就添加一个firstTask为null的线程
3)队列都塞满了就加大线程数(maximumPoolSize),带着任务去创建并启动新的线程
image
检查是否可以根据当前线程池状态和给定界限(核心或最大值)添加新的工作线程。
如果可以就相应地增加工作线程数量,并且将创建并启动一个新的工作线程,
将firstTask作为其第一个任务运行。如果线程池已停止或可以关闭,则此方法返回false。
如果线程工厂判定不能创建线程,它也会返回false。
如果线程创建失败,要么是由于线程工厂返回null,要么是由于异常(通常是Thread.start()中的OutOfMemoryError)我们会干净利落地回滚。
image

image

干活的工人(线程)叫起来了,那么任务呢?从哪开始干呢?进入Worker这个车间看看去吧。
不废话了,AQS以后再说,直接跳到这个线程类的run方法中去吧,可以看到里面很顺滑的执行了runWorker()方法,这就是干活的地方吧。没错,这就是线程池真正执行你提交的任务的地方。
image
至此貌似可以完结了,总感觉少了点什么,那么重点进入上面的这一行代码中去看看吧,重点的地方都注释了
image
image
以上

posted @ 2021-09-06 08:22  爆炸橙子  阅读(31)  评论(0编辑  收藏  举报