tomcat在哪里用到了线程池
- LimitLatch用来限流,可以控制最大连接个数
- acceptor负责接收新的socket连接
- poller负责监听socket channel是否有可读的IO事件
- 一旦有可读的IO事件被监听到,就封装一个任务对象socketProcessor,提交给executor线程池处理
- executor线程池中的工作线程最终负责处理请求
tomcat线程池扩展了ThreadPoolExecutor:
如果总线程达到了最大线程数,不会立刻抛出RejectedExecutionException异常,而是会再次尝试将任务放入队列,如果还是失败,才会抛出RejectedExecutionException异常。
tomcat-7.0.42部分源码
public void execute (Runnable command,long timeout, TimeUnit unit){
submittedCount.incrementAndGet();
try {
// 执行任务
super.execute(command);
// 出现异常
} catch (RejectedExecutionException rx) {
// 尝试将任务先放入队列,如果失败,才再次抛出异常
if (super.getQueue() instanceof TaskQueue) {
final TaskQueue queue = (TaskQueue) super.getQueue();
try {
if (!queue.force(command, timeout, unit)) {
submittedCount.decrementAndGet();
throw new RejectedExecutionException("Queue capacity is full.");
}
} catch (InterruptedException x) {
submittedCount.decrementAndGet();
Thread.interrupted();
throw new RejectedExecutionException(x);
}
} else {
submittedCount.decrementAndGet();
throw rx;
}
}
}
TaskQueue的force方法:将任务放入等待队列
public boolean force(Runnable o, long timeout, TimeUnit unit) throws InterruptedException {
if ( parent.isShutdown() )
throw new RejectedExecutionException(
"Executor not running, can't force a command into the queue"
);
return super.offer(o,timeout,unit); //forces the item onto the queue, to be used if the task
is rejected
}
tomcat添加新任务的流程
如果提交的任务数 < 核心线程数,那么任务直接被提交到任务队列等待执行
如果提交的任务数 >= 核心线程数,且提交的任务数 < 最大线程数,那么也加入任务队列等待运行
如果提交的任务数 >= 最大线程数, 那么就创建救急线程运行任务