Tomcat如何扩展线程池?

Tomcat线程池扩展了原生的ThreadPoolExecutor

通过重写execute方法实现了自己的任务处理逻辑:

corePoolSize个任务时,来一个任务就创建一个新线程。

再来任务的话,就把任务添加到任务队列里让所有的线程去抢,如果队列满了就创建临时线程。

如果总线程数达到maximumPoolSize,则继续尝试把任务添加到任务队列中去。

如果缓冲队列也满了,插入失败,执行拒绝策略。

Tomcat在线程总数达到最大数时,不是立即执行拒绝策略。

  • 而是再尝试向任务队列添加任务,添加失败后再执行拒绝策略。

默认情况下Tomcat的任务队列是没有限制的,可以通过设置maxQueueSize参数来限制任务队列的长度。

因为Tomcat属于IO密集型:

所以才优先尝试新建线程,线程池满载了,再添加任务到阻塞队列里排队等待。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class ThreadPoolExecutor extends java.util.concurrent.ThreadPoolExecutor {

...

public void execute(Runnable command, long timeout, TimeUnit unit) {
submittedCount.incrementAndGet();
try {
//调用Java原生线程池的execute去执行任务
super.execute(command);
} catch (RejectedExecutionException rx) {
//如果总线程数达到maximumPoolSize,Java原生线程池执行拒绝策略
if (super.getQueue() instanceof TaskQueue) {
final TaskQueue queue = (TaskQueue)super.getQueue();
try {
//继续尝试把任务放到任务队列中去
if (!queue.force(command, timeout, unit)) {
submittedCount.decrementAndGet();
//如果缓冲队列也满了,插入失败,执行拒绝策略。
throw new RejectedExecutionException("...");
}
}
}
}
}