tomcat基于java线程池进行扩展,通过自定义队列,线程工厂,任务处理流程。在确保请求不会丢失的情况下,限制高并发防止系统资源耗尽。
StandardThreadExecutor中startInternal执行具体tomcat线程池创建流程。
/**
* max number of threads
*/
protected int maxThreads = 200;
/**
* min number of threads
*/
protected int minSpareThreads = 25;
/**
* idle time in milliseconds
*/
protected int maxIdleTime = 60000;
/**
* The maximum number of elements that can queue up before we reject them
*/
protected int maxQueueSize = Integer.MAX_VALUE;
@Override
protected void startInternal() throws LifecycleException {
// 自定义Integer.MAX_VALUE长度队列
taskqueue = new TaskQueue(maxQueueSize);
// 自定义线程工厂
TaskThreadFactory tf = new TaskThreadFactory(namePrefix,daemon,getThreadPriority());
// 继承java.util.concurrent.ThreadPoolExecutor创建流程不变
executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), maxIdleTime, TimeUnit.MILLISECONDS,taskqueue, tf);
executor.setThreadRenewalDelay(threadRenewalDelay);
if (prestartminSpareThreads) {
executor.prestartAllCoreThreads();
}
taskqueue.setParent(executor);
setState(LifecycleState.STARTING);
}
通过创建流程可能还看不出tomcat线程池优势,其具体实现在org.apache.tomcat.util.threads.ThreadPoolExecutor类execute方法中。tomcat线程池以java线程池执行模式执行,当发生拒绝策略时仍把请求放入队列,保证请求不丢失。
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(sm.getString("threadPoolExecutor.queueFull"));
}
} catch (InterruptedException x) {
submittedCount.decrementAndGet();
throw new RejectedExecutionException(x);
}
} else {
submittedCount.decrementAndGet();
throw rx;
}
}
}
进入execute方法,均为java线程池执行流程,需要注意的是workQueue.offer方法,tomcat自定义队列时重写了此方法。由于java线程池处理逻辑为队列满了才会创建临时线程,但创建队列时队列长度为Integer.MAX_VALUE,队列几乎不会被填满,所以tomcat通过以下代码判断是否创建临时线程。
@Override
public boolean offer(Runnable o) {
//we can't do any checks
if (parent==null) return super.offer(o);
// 如果线程数达到最大值,不能创建新线程,将任务放入队列
if (parent.getPoolSize() == parent.getMaximumPoolSize()) return super.offer(o);
// 如果已提交的任务数小于当前线程数,将任务放入队列
if (parent.getSubmittedCount()<(parent.getPoolSize())) return super.offer(o);
// 如果线程数小于最大线程,返回false创建新线程
if (parent.getPoolSize()<parent.getMaximumPoolSize()) return false;
//if we reached here, we need to add it to the queue
return super.offer(o);
}