Java线程池架构(一)原理和源码解析(Java线程池原理及源码深度解析(一))
原创
一、Java线程池简介
Java线程池是一种用于管理多个线程的工具,它能够有效地管理线程的生命周期,尽或许降低损耗程序性能。Java线程池的核心是Executor框架,它提供了线程池的创建、管理以及任务提交等功能。在Java中,线程池的实现重点是通过ThreadPoolExecutor类来完成的。
二、线程池的核心参数
线程池的核心参数包括以下几个:
- corePoolSize:线程池的基本大小。
- maximumPoolSize:线程池最大线程数。
- keepAliveTime:当线程数大于核心线程数时,这是多余空闲线程在终止前等待新任务的最长时间。
- unit:keepAliveTime的时间单位。
- workQueue:工作队列,用于存放还未执行的任务。
- threadFactory:线程工厂,用于创建新线程。
- handler:拒绝策略,当任务太多无法处理时,采取的策略。
三、线程池的工作流程
线程池的工作流程可以分为以下几个步骤:
- 当有新任务提交时,首先检查线程池中的线程数量是否小于corePoolSize。
- 如果小于corePoolSize,则创建新线程来执行任务。
- 如果线程池中的线程数量大于等于corePoolSize,但小于maximumPoolSize,并且工作队列未满,则将任务放入工作队列。
- 如果工作队列已满,但线程池中的线程数量小于maximumPoolSize,则创建新线程来执行任务。
- 如果线程池中的线程数量等于maximumPoolSize,则采取拒绝策略处理任务。
四、源码解析
下面我们来分析ThreadPoolExecutor类的核心源码。
4.1 类的继承结构
public class ThreadPoolExecutor extends AbstractExecutorService
implements ExecutorService {
// ...
}
ThreadPoolExecutor类继承了AbstractExecutorService类,并实现了ExecutorService接口。AbstractExecutorService类提供了线程池的基本实现,而ExecutorService接口定义了线程池的核心方法。
4.2 构造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue
workQueue, ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.workQueue = workQueue;
this.threadFactory = threadFactory;
this.handler = handler;
}
构造方法接收了线程池的核心参数,并对参数进行了校验。然后,将这些参数赋值给类的成员变量。
4.3 execute方法
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (!isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
}
execute方法是线程池的核心方法,用于提交任务。该方法首先检查任务是否为null,然后尝试创建新线程执行任务。如果线程池中的线程数量小于corePoolSize,则调用addWorker方法创建新线程。如果创建顺利,则直接返回。如果创建未果,则将任务放入工作队列。如果工作队列已满,则尝试创建新线程,如果仍然未果,则采取拒绝策略。
4.4 addWorker方法
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty())) {
return false;
}
for (;;) {
int wc = workerCountOf(c);
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize)) {
return false;
}
if (compareAndIncrementWorkerCount(c))
break retry;
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
}
}
boolean workerStarted = false;
Thread w = null;
try {
w = threadFactory.newThread(this);
final Thread t = w;
final Runnable firstTask = this.firstTask;
this.firstTask = null;
w.start();
workerStarted = true;
} catch (Throwable ex) {
// ...
}
return workerStarted;
}
addWorker方法是线程池中创建新线程的核心方法。该方法首先检查线程池的状态,然后检查线程池中的线程数量是否已约为上限。如果线程数量未约为上限,则通过threadFactory创建新线程,并启动线程。
五、总结
本文对Java线程池的原理进行了简要介绍,并分析了ThreadPoolExecutor类的核心源码。线程池是一种高效的任务管理工具,通过合理地配置线程池参数,可以尽或许降低损耗程序性能。在后续的文章中,我们将继续深入探讨线程池的其他方面,如线程池的拒绝策略、工作队列的选择等。