Tomcat的线程池和我们传统意义上使用的线程池稍微有些许差别,但是差别不大。他们的区别在于Tomcat线程池会先将Max Thread Size跑满,然后再去填充队列,而传统的线程池使用方式则是将队列跑满,再去扩容最大线程数。

    Tomcat的线程使用在 org.apache.catalina.core.StandardThreadExecutor

    1. protected void startInternal() throws LifecycleException {
    2. this.taskqueue = new TaskQueue(this.maxQueueSize);
    3. TaskThreadFactory tf = new TaskThreadFactory(this.namePrefix, this.daemon, this.getThreadPriority());
    4. this.executor = new ThreadPoolExecutor(this.getMinSpareThreads(), this.getMaxThreads(), (long)this.maxIdleTime, TimeUnit.MILLISECONDS, this.taskqueue, tf);
    5. this.executor.setThreadRenewalDelay(this.threadRenewalDelay);
    6. if (this.prestartminSpareThreads) {
    7. this.executor.prestartAllCoreThreads();
    8. }
    9. this.taskqueue.setParent(this.executor);
    10. this.setState(LifecycleState.STARTING);
    11. }

    而跑满最大线程数的秘密则是隐藏在TaskQueue中

    实现理论:都知道线程池提交任务扩容最大线程是取决于队列是否满 queue.offer ,那么只要offer失败了,那么自然就会启动最大线程数。

    1. public boolean offer(Runnable o) {
    2. if (this.parent == null) {
    3. return super.offer(o);
    4. } else if (this.parent.getPoolSize() == this.parent.getMaximumPoolSize()) {
    5. return super.offer(o);
    6. } else if (this.parent.getSubmittedCount() <= this.parent.getPoolSize()) {
    7. return super.offer(o);
    8. } else {
    9. return this.parent.getPoolSize() < this.parent.getMaximumPoolSize() ? false : super.offer(o);
    10. }
    11. }