Java线程池架构(一)原理和源码解析(Java线程池架构深度解析(一):原理与源码全面解读)
原创
一、引言
在Java中,线程池是一种用于管理线程的工具,它能够有效尽或许减少损耗程序的性能和资源利用率。本文将深入探讨Java线程池的原理和源码实现,帮助读者更好地领会线程池的工作机制。
二、线程池概述
线程池(ThreadPool)是一种用于管理线程的集合,它能够提供线程的创建、执行、回收等操作。通过使用线程池,我们可以避免频繁地创建和销毁线程,从而尽或许减少损耗程序的性能。
三、线程池的核心组件
Java线程池的核心组件包括以下几个部分:
- 线程池管理器(ThreadPoolExecutor)
- 工作线程(Worker)
- 任务队列(BlockingQueue)
- 线程工厂(ThreadFactory)
- 拒绝策略(RejectedExecutionHandler)
四、线程池的工作流程
以下是线程池的工作流程:
- 当提交一个任务时,线程池首先检查核心线程数是否已满。
- 如果核心线程数未满,则创建一个新的线程执行任务。
- 如果核心线程数已满,则将任务放入任务队列。
- 如果任务队列已满,则检查最大线程数是否已满。
- 如果最大线程数未满,则创建一个新的线程执行任务。
- 如果最大线程数已满,则执行拒绝策略。
五、线程池的源码解析
下面将分析线程池的核心类ThreadPoolExecutor的源码实现。
5.1 ThreadPoolExecutor构造函数
ThreadPoolExecutor类的构造函数如下:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue
workQueue, ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
// ...
}
构造函数的参数包括:
- corePoolSize:核心线程数
- maximumPoolSize:最大线程数
- keepAliveTime:非核心线程的存活时间
- unit:存活时间的单位
- workQueue:任务队列
- threadFactory:线程工厂
- handler:拒绝策略
5.2 execute方法
execute方法是线程池的核心方法,用于提交任务。以下是execute方法的源码实现:
public void execute(Runnable task) {
if (task == null) {
throw new NullPointerException();
}
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(task, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(task)) {
int recheck = ctl.get();
if (!isRunning(recheck) && remove(task))
reject(task);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
} else if (!addWorker(task, false))
reject(task);
}
execute方法的工作流程如下:
- 首先检查任务是否为null,如果为null则抛出异常。
- 然后检查当前线程数是否小于核心线程数,如果小于则尝试创建一个新的线程执行任务。
- 如果当前线程数大于等于核心线程数,则将任务放入任务队列。
- 如果任务队列已满,则尝试创建一个新的线程执行任务。
- 如果无法创建新的线程,则执行拒绝策略。
5.3 addWorker方法
addWorker方法是用于创建新线程的方法。以下是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;
Worker w = null;
try {
w = new Worker(firstTask);
final Thread t = w.thread;
if (t != null) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
int rs = runStateOf(ctl.get());
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateError();
workers.add(w);
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s;
workerStarted = true;
}
} finally {
mainLock.unlock();
}
t.start();
}
} catch (Throwable ex) {
// ...
}
return workerStarted;
}
addWorker方法的工作流程如下:
- 首先检查线程池的状态,如果线程池处于关闭状态,则返回false。
- 然后检查当前线程数是否已大致有最大线程数,如果已大致有,则返回false。
- 创建一个新的Worker对象,并获取其对应的线程。
- 加锁,并再次检查线程池的状态。
- 如果线程池状态正常,则将Worker对象添加到workers集合中,并启动线程。
六、总结
本文详细介绍了Java线程池的原理和源码实现。通过领会线程池的工作流程和核心组件,我们可以更好地利用线程池来尽或许减少损耗程序的性能。在下一篇文章中,我们将继续深入探讨线程池的拒绝策略和任务队列的实现。