关于线程池的几个问题?
参考:
- 它的核心参数是哪些?
- 添加任务的逻辑是什么?
- 获取并执行任务的逻辑是什么?
- 当线程池空闲时怎么删除多余线程的?
- 有哪些需要特别注意的点?
它的核心参数是哪些
- corePoolSize : 任务队列未达到队列容量时,最大可以同时运行的线程数量。
- maximumPoolSize : 任务队列中存放的任务达到队列容量的时候,当前可以同时运行的线程数量变为最大线程数。
- workQueue: 新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,新任务就会被存放在队列中。
- handler :拒绝策略
添加任务的逻辑是什么
- 如果当前运行的线程数小于核心线程数,那么就会新建一个线程来执行任务。
- (假如corePoolSize=5,此时只有1个任务在运行中,又添加1个任务,还是会创建新线程。)
- (假如corePoolSize=5,此时已成功运行过3个任务,又添加1个任务,还是会创建新线程,而不是复用这3个线程。)
- 如果当前运行的线程数等于或大于核心线程数,但是小于最大线程数,那么就把该任务放入到任务队列里等待执行。
- 如果向任务队列投放任务失败(任务队列已经满了),但是当前运行的线程数是小于最大线程数的,就新建一个线程来执行任务。
- 如果当前运行的线程数已经等同于最大线程数了,新建线程将会使当前运行的线程超出最大线程数,那么当前任务会被拒绝,拒绝策略会调用RejectedExecutionHandler.rejectedExecution()方法。
获取并执行任务的逻辑是什么
因为我们提交的任务Runnabale是以Worker这个对象去运行。
// 在java.util.concurrent.ThreadPoolExecutor中
private final class Worker
extends AbstractQueuedSynchronizer
implements Runnable
{
}
java.util.concurrent.ThreadPoolExecutor#addWorker中会创建Worker,并调用Worker#thread的start()方法。
// 在java.util.concurrent.ThreadPoolExecutor中
Worker w = null;
try {
// 此处创建Worker
w = new Worker(firstTask);
final Thread t = w.thread;
if (t != null) {
...
if (workerAdded) {
// 此处执行线程t
container.start(t);
...
}
}
}
// new Worker(firstTask)
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
// 注意:创建的thread中是把当前worker传进去的
this.thread = getThreadFactory().newThread(this);
}
container.start(t)跟着调用到这里。
// 在java.lang.System中
public void start(Thread thread, ThreadContainer container) {
thread.start(container);
}
最终会调用到Worker的run()方法,别忘记它是一个Runnable。
// 在java.util.concurrent.ThreadPoolExecutor.Worker中
public void run() {
runWorker(this);
}
runWorker会使用firstTask或从workQueue中获取任务去执行。
// 在java.util.concurrent.ThreadPoolExecutor中
private Runnable getTask() {
...
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// 当我们调用shutdown()的时候 线程池状态是SHUTDOWN,调用shutdownNow()的时候线程状态是STOP,那么这2种状态是怎么处理阻塞队列里面的任务的呢?代码如下,
// 当状态是SHUTDOWN的时候,只有 队列为空的时候 才会返回null
// 当状态是STOP的时候,直接返回的null
// 说明 SHUTDOWN<STOP
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
}
...
}
最后 用一张流程图,来描述下一个任务从添加到运行结束,经历了哪些方法!

说明:图片来自ThreadPoolExecutor是怎么去执行一个任务的?前面一遍文章 我们看了下FutureTask的源码,知道了怎 - 掘金
作者:张三 创建时间:2025-02-28 19:20
最后编辑:张三 更新时间:2025-03-05 18:56
最后编辑:张三 更新时间:2025-03-05 18:56