- 为啥要优化
1、由于tomcat 处理的都是一些网络方面的线程任务,都是IO类型的 2、JDK原生线程池,当核心线程满了之后往队列里面存放,这样不符合web容器的任务 3、tomcat修改为,核心线程满了之后,再创建非核心线程。最后再往队列任务里面存放
- 优化的手段
public void execute(Runnable command) { if (command == null) throw new NullPointerException(); int c = ctl.get(); if (workerCountOf(c) < corePoolSize) { if (addWorker(command, true)) return; c = ctl.get(); } if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); if (! isRunning(recheck) && remove(command)) reject(command); else if (workerCountOf(recheck) == 0) addWorker(null, false); } else if (!addWorker(command, false)) reject(command); }
上述代码中 workQueue.offer(command) 这里的逻辑可以换成,非核心线程未满都返回false。这样就可以创建非核心线程了
队列进行定制为TaskQueue
- TaskQueue核心代码如下
@Override public boolean offer(Runnable o) { //we can't do any checks if (parent==null) return super.offer(o); //we are maxed out on threads, simply queue the object if (parent.getPoolSize() == parent.getMaximumPoolSize()) return super.offer(o); //we have idle threads, just add it to the queue if (parent.getSubmittedCount()<(parent.getPoolSize())) return super.offer(o); //if we have less threads than maximum force creation of a new thread if (parent.getPoolSize()<parent.getMaximumPoolSize()) return false; //if we reached here, we need to add it to the queue return super.offer(o); }
- tomcat的线程池对象也定制了一下,主要不同点为
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();
throw new RejectedExecutionException(x);
}
} else {
submittedCount.decrementAndGet();
throw rx;
}
}
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
submittedCount.decrementAndGet();
if (t == null) {
stopCurrentThreadIfNeeded();
}
}
增加了重试功能 ,被拒绝之后,直接强制往队列里面放
备注:变量 submittedCount 是为了统计已经提交到线程池但还没有完成任务的数目 这里变量会在TaskQueue offer方法里面使用,看是否存在空闲的线程