没有合适的资源?快使用搜索试试~ 我知道了~
12-线程池ThreadPoolExecutor底层原理源码分析(下)-周瑜.pdf
需积分: 2 2 下载量 119 浏览量
2024-02-28
14:59:57
上传
评论
收藏 374KB PDF 举报
温馨提示
试读
20页
11-线程池 ThreadPoolExecutor 底层原理源码分析(上)-周瑜.pdf 12-线程池 ThreadPoolExecutor底层原理源码分析(下)-周瑜.pdf 13、线程池 ForkJoinPool实战及其工作原理分析 (1).pdf 14、深入理解井发可见性、有序性、原子性与JMM内存模型 (1).pdf 15、CPU缓存架构详解&高性能内存队列Disruptor 实战 (1).pdf 16、常用并发设计模式精讲 (1).pdf designpattern.zip disruptor.zip forkjoin.zip jmm(1).zip
资源推荐
资源详情
资源评论
课程内容:
1、线程池中基本属性和方法源码解析
2、线程池的五种状态变换源码分析
3、线程池添加线程源码解析
4、线程池线程运行执行任务源码解析
5、线程池shutdown源码解析
6、线程池中线程退出机制源码解析
有道云链接:
在线程池的源码中,会通过一个AtomicInteger类型的变量ctl,来表示线程池的状态和当前线程池中
的工作线程数量。
一个Integer占4个字节,也就是32个bit,线程池有5个状态:
2个bit能表示4种状态,那5种状态就至少需要三个bit位,比如在线程池的源码中就是这么来表示的:
Integer.SIZE为32,所以COUNT_BITS为29,最终各个状态对应的二级制为:
https://note.youdao.com/s/5GiBpVIX
线程池源码的基础属性和方法
RUNNING
SHUTDOWN
STOP
TIDYING
TERMINATED
private static final int COUNT_BITS = Integer.SIZE - 3;1
2
private static final int RUNNING = -1 << COUNT_BITS;3
private static final int SHUTDOWN = 0 << COUNT_BITS;4
private static final int STOP = 1 << COUNT_BITS;5
private static final int TIDYING = 2 << COUNT_BITS;6
private static final int TERMINATED = 3 << COUNT_BITS;7
RUNNING:11100000 00000000 00000000 00000000
SHUTDOWN:00000000 00000000 00000000 00000000
STOP:00100000 00000000 00000000 00000000
TIDYING:01000000 00000000 00000000 00000000
TERMINATED:01100000 00000000 00000000 00000000
1.
2.
3.
4.
5.
1.
2.
3.
4.
5.
所以,只需要使用一个Integer数字的最高三个bit,就可以表示5种线程池的状态,而剩下的29个bit就
可以用来表示工作线程数,比如,假如ctl为:11100000 00000000 00000000 00001010,就表示
线程池的状态为RUNNING,线程池中目前在工作的线程有10个,这里说的“在工作”意思是线程活
着,要么在执行任务,要么在阻塞等待任务。
同时,在线程池中也提供了一些方法用来获取线程池状态和工作线程数,比如:
同时,还有一个方法:
就是用来把运行状态和工作线程数量进行合并的一个方法,不过传入这个方法的两个int数字有限制,
rs的低29位都得为0,wc的高3位都得为0,这样经过或运算之后,才能得到准确的ctl。
同时,还有一些相关的方法:
// 29,二进制为00000000 00000000 00000000 000111011
private static final int COUNT_BITS = Integer.SIZE - 3;2
3
// 00011111 11111111 11111111 111111114
private static final int CAPACITY = (1 << COUNT_BITS) - 1;5
6
// ~CAPACITY为11100000 00000000 00000000 000000007
// &操作之后,得到就是c的高3位8
private static int runStateOf(int c) { 9
return c & ~CAPACITY; 10
}11
12
// CAPACITY为00011111 11111111 11111111 1111111113
// &操作之后,得到的就是c的低29位14
private static int workerCountOf(int c) { 15
return c & CAPACITY; 16
}17
private static int ctlOf(int rs, int wc) { 1
return rs | wc; 2
}3
前面说到线程池有5个状态,这5个状态分别表示:
private static final int RUNNING = -1 << COUNT_BITS;1
private static final int SHUTDOWN = 0 << COUNT_BITS;2
private static final int STOP = 1 << COUNT_BITS;3
private static final int TIDYING = 2 << COUNT_BITS;4
private static final int TERMINATED = 3 << COUNT_BITS;5
6
// c状态是否小于s状态,比如RUNNING小于SHUTDOWN7
private static boolean runStateLessThan(int c, int s) {8
return c < s;9
}10
11
// c状态是否大于等于s状态,比如STOP大于SHUTDOWN12
private static boolean runStateAtLeast(int c, int s) {13
return c >= s;14
}15
16
// c状态是不是RUNNING,只有RUNNING是小于SHUTDOWN的17
private static boolean isRunning(int c) {18
return c < SHUTDOWN;19
}20
21
// 通过cas来增加工作线程数量,直接对ctl进行加122
// 这个方法没考虑是否超过最大工作线程数的(2的29次方)限制,源码中在调用该方法之前会进行判断的23
private boolean compareAndIncrementWorkerCount(int expect) {24
return ctl.compareAndSet(expect, expect + 1);25
}26
27
// 通过cas来减少工作线程数量,直接对ctl进行减128
private boolean compareAndDecrementWorkerCount(int expect) {29
return ctl.compareAndSet(expect, expect - 1);30
}31
RUNNING:线程池正常运行中,可以正常的接受并处理任务
SHUTDOWN:线程池关闭了,不能接受新任务,但是线程池会把阻塞队列中的剩余任务执行完,剩余任务都处
理完之后,会中断所有工作线程
STOP:线程池停止了,不能接受新任务,并且也不会处理阻塞队列中的任务,会中断所有工作线程
TIDYING:当前线程池中的工作线程都被停止后,就会进入TIDYING
1.
2.
3.
4.
当执行线程池的execute方法时:
TERMINATED:线程池处于TIDYING状态后,会执行terminated()方法,执行完后就会进入TERMINATED状
态,在ThreadPoolExecutor中terminated()是一个空方法,可以自定义线程池重写这个方法
execute方法
public void execute(Runnable command) {1
2
if (command == null)3
throw new NullPointerException();4
5
// 获取ctl6
// ctl初始值是ctlOf(RUNNING, 0),表示线程池处于运行中,工作线程数为07
int c = ctl.get();8
9
// 工作线程数小于corePoolSize,则添加工作线程,并把command作为该线程要执行的任务10
if (workerCountOf(c) < corePoolSize) {11
// true表示添加的是核心工作线程,具体一点就是,在addWorker内部会判断当前工作
线程数是不是超过了corePoolSize
12
// 如果超过了则会添加失败,addWorker返回false,表示不能直接开启新的线程来执
行任务,而是应该先入队
13
if (addWorker(command, true))14
return;15
16
// 如果添加核心工作线程失败,那就重新获取ctl,可能是线程池状态被其他线程修改
了
17
// 也可能是其他线程也在向线程池提交任务,导致核心工作线程已经超过了
corePoolSize
18
c = ctl.get();19
}20
21
// 线程池状态是否还是RUNNING,如果是就把任务添加到阻塞队列中22
if (isRunning(c) && workQueue.offer(command)) {23
24
// 在任务入队时,线程池的状态可能也会发生改变25
// 再次检查线程池的状态,如果线程池不是RUNNING了,那就不能再接受任务了,就得
把任务从队列中移除,并进行拒绝策略
26
27
// 如果线程池的状态没有发生改变,仍然是RUNNING,那就不需要把任务从队列中移除
掉
28
5.
剩余19页未读,继续阅读
资源评论
代码匠心印记
- 粉丝: 483
- 资源: 30
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功