java 线程池实现原理
作者:互联网
ThreadPoolExecutor 继承了 AbstractExecutorService,成员变量 ctl 是个 Integer 的原子变量用来记录线程池状态 和 线程池中线程个数,类似于 ReentrantReadWriteLock 使用一个变量存放两种信息。
//用来标记线程池状态(高3位),线程个数(低29位)
//默认是RUNNING状态,线程个数为0
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
//线程个数掩码位数,并不是所有平台int类型是32位,所以准确说是具体平台下Integer的二进制位数-3后的剩余位数才是线程的个数,
private static final int COUNT_BITS = Integer.SIZE - 3;
//线程最大个数(低29位)00011111111111111111111111111111
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
线程池状态含义:
RUNNING:接受新任务并且处理阻塞队列里的任务;
SHUTDOWN:拒绝新任务但是处理阻塞队列里的任务;
STOP:拒绝新任务并且抛弃阻塞队列里的任务,同时会中断正在处理的任务;
TIDYING:所有任务都执行完(包含阻塞队列里面任务)当前线程池活动线程为 0,将要调用 terminated 方法;
TERMINATED:终止状态,terminated方法调用完成以后的状态。
线程池状态转换:
1.RUNNING -> SHUTDOWN:显式调用 shutdown() 方法,或者隐式调用了 finalize(),它里面调用了 shutdown() 方法。
2.RUNNING or SHUTDOWN -> STOP:显式调用 shutdownNow() 方法时候。
3.SHUTDOWN -> TIDYING:当线程池和任务队列都为空的时候。
4.STOP -> TIDYING:当线程池为空的时候。
5.TIDYING -> TERMINATED:当 terminated() hook 方法执行完成时候。
线程池参数:
corePoolSize:线程池核心线程个数;
workQueue:用于保存等待执行的任务的阻塞队列;比如基于数组的有界 ArrayBlockingQueue,基于链表的无界 LinkedBlockingQueue,最多只有一个元素的同步队列 SynchronousQueue,优先级队列 PriorityBlockingQueue 等。
maximunPoolSize:线程池最大线程数量。
ThreadFactory:创建线程的工厂。
RejectedExecutionHandler:饱和策略,当队列满了并且线程个数达到 maximunPoolSize 后采取的策略,比如 AbortPolicy (抛出异常),CallerRunsPolicy(使用调用者所在线程来运行任务),DiscardOldestPolicy(调用 poll 丢弃一个任务,执行当前任务),DiscardPolicy(默默丢弃,不抛出异常)。
keeyAliveTime:存活时间。如果当前线程池中的线程数量比核心线程数量要多,并且是闲置状态的话,这些闲置的线程能存活的最大时间。
TimeUnit,存活时间的时间单位。
线程池的实现主要依赖以下以下类和方法:
Worker:实现了Runnable接口用于实现线程复用,线程执行的载体
addWorker:添加一个worker执行线程
RunWorker:执行worker中线程的run方法
worker中有一个Thread类的成员变量,这个线程就是worker要执行的线程。 runworker中是一个while循环,只要存在task或者可以获取到新的task就会继续执行
private final class Worker implements Runnable {
final Thread thread;
Runnable firstTask;
Worker(Runnable firstTask) {
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
public void run() {
runWorker(this);
}
final void runWorker(Worker w) {
Runnable task = w.firstTask;
w.firstTask = null;
while (task != null || (task = getTask()) != null){
task.run();
}
}
private Runnable getTask() {
if(一些特殊情况) {
return null;
}
Runnable r = workQueue.take();
return r;
}
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
// 当前线程数 < corePoolSize
if (workerCountOf(c) < corePoolSize) {
// 直接启动新的线程。
if (addWorker(command, true))
return;
c = ctl.get();
}
// 活动线程数 >= corePoolSize
// runState为RUNNING && 队列未满
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
// 再次检验是否为RUNNING状态
// 非RUNNING状态 则从workQueue中移除任务并拒绝
if (!isRunning(recheck) && remove(command))
reject(command);// 采用线程池指定的策略拒绝任务
// 两种情况:
// 1.非RUNNING状态拒绝新的任务
// 2.队列满了启动新的线程失败(workCount > maximumPoolSize)
} else if (!addWorker(command, false))
reject(command);
}
private boolean addWorker(Runnable firstTask, boolean core) {
int wc = workerCountOf(c);
if (wc >= (core ? corePoolSize : maximumPoolSize)) {
return false;
}
w = new Worker(firstTask);
final Thread t = w.thread;
t.start();
}
标签:Runnable,java,队列,command,RUNNING,线程,firstTask,原理 来源: https://blog.csdn.net/weixin_39650169/article/details/114301915