最近在学习Java基础,正在阅读《Java并发编程实战》,该书总结的规律性内容偏多,关于JDK底层实现介绍较少,为提升Java多线程基础,萌生了阅读concurrent包源码的想法,夯实基础,从阅读源码开始ヾ(◍°∇°◍)ノ゙
UML类图
![](https://img.haomeiwen.com/i7108809/f052ba79207b8724.png)
函数调用关系
![](https://img.haomeiwen.com/i7108809/6d955c53e00af8b2.png)
线程池中的基本概念
基础概念
定义
线程池是一种生产者-消费者的模型,底层基于阻塞队列+ReentrantLock+CAS+volitate+原子类实现线程安全。线程池中有两个基础概念:工作线程和任务。用户提交任务,线程池为任务分配工作线程(1:N),线程池中的工作线程属于内部类Worker的实例。其中firstTask代表工作线程将要执行的任务,thread表示执行任务的线程,thread由线程工场负责创建。
private final class Worker extends AbstractQueuedSynchronizer implements Runnable
{
final Thread thread;
Runnable firstTask;
volatile long completedTasks;
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
public void run() {
runWorker(this);
}
}
线程池生命周期
![](https://img.haomeiwen.com/i7108809/514076858cabe1cc.png)
基本属性
- ctl 线程池的状态代码,ctl是原子类的Integer 32bit,包含了两种信息:其中最高的3bit代表线程池的状态runState,剩余的表示线程池中的有效可用线程数workerCount。
- 利用CAS的方式更新线程池状态以及workerCount
- 这里为什么要这样设计呢?
[1] AutoInteger原子类保证了线程安全
[2] 状态和数量用一个数值表示,利用位运算获得状态和数量,效率更高??- workerCount != 线程池存活线程数,具体指的是什么?不是很懂
-
workQueue 阻塞队列,保存用户提交的任务。
-
mainLock 线程池的ReentrantLock,在对工作线程进行操作之前需要获得这个锁,保证线程安全。
所有涉及到worker的操作都需要首先获取锁(这是由于worker为HashSet属于线程不安全的类)
没有用内置锁,这是因为需要可重入
-
threadFactory 线程池利用threadFactory新建线程。
-
corePoolSize 线程池中的核心线程数,线程池中可用线程的最小数。
-
largestPoolSize 线程池核心最大线程数,线程池中可用线程的最大数。
-
keep-alive time 核心线程允许空转的最长时间。当线程池中的线程数量>corePoolSieze空转的线程超过keep-alive time后会被terminated。
-
workers 线程池工作线程的HashSet集合,包含了线程池执行任务的线程
HashSet线程不安全因此每次在访问这个成员变量时需要获取ReentrantLock
重要方法
execute()
execute用于尝试接收用户提交的任务,并执行拒绝策略。
![](https://img.haomeiwen.com/i7108809/c7169d9e35ad7750.png)
addWorker()
addWorker用于执行用户提交的任务。首先检查线程池状态,线程池只有在Running状态和阻塞队列不为空的情况下才会执行任务,否则直接返回。
具体处理逻辑如下图所示
![](https://img.haomeiwen.com/i7108809/f04e5ee258016804.png)
疑问
- 线程池利用ReentrantLock保证线程安全,为什么在每个方法内部需要final ReentrantLock mianLock重新引用呢?
public long getTaskCount() {
final ReentrantLock mainLock = this.mainLock;//这里为什么一定要再次引用一下呢??
mainLock.lock();
try {
long n =completedTaskCount;
for (Worker w :workers) {
n += w.completedTasks;
if (w.isLocked())
++n;
}
return n +workQueue.size();
}finally {
mainLock.unlock();
}
}
网友评论