编辑
2023-11-08
Tomcat源码学习
00
请注意,本文编写于 549 天前,最后修改于 549 天前,其中某些信息可能已经过时。

Tomcat如何扩展Java线程池

在Tomcat中,可以通过定制化的方式来扩展Java线程池,以满足特定的业务需求。下面是关于如何扩展Java线程池的一些总结:

  1. Java线程池

Java线程池是通过ThreadPoolExecutor类来创建的,它具有以下参数:

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)

Java线程池的处理逻辑如下:

  • 前corePoolSize个任务,每来一个任务就创建一个新线程。
  • 后续的任务会被添加到工作队列workQueue中,等待线程池中的线程来执行。
  • 如果工作队列已满,且线程池中的线程数还未达到maximumPoolSize,则会创建临时线程来执行任务。
  • 如果线程池中的线程数已达到maximumPoolSize,且工作队列也已满,则会执行拒绝策略handler。
  1. Tomcat线程池

Tomcat的线程池是基于ThreadPoolExecutor进行定制化的,主要是为了限制线程个数和队列长度,以避免资源耗尽的风险。以下是Tomcat线程池的一些特点:

2.1 定制版ThreadPoolExecutor

Tomcat构建线程池的代码如下:

TaskQueue taskqueue = new TaskQueue(); TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-", daemon, getThreadPriority()); executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS, taskqueue, tf);
  • Tomcat定制了任务队列和线程工厂。
  • Tomcat对线程数也有限制,设置了核心线程数(minSpareThreads)和最大线程池数量(maxThreads)。

2.2 定制版任务队列

Tomcat的定制版任务队列是TaskQueue,它是对Java的LinkedBlockingQueue进行了扩展。TaskQueue的offer方法被重写,用于控制任务的添加逻辑。具体逻辑如下:

public Boolean offer(Runnable o) { 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); } if (parent.getPoolSize() < parent.getMaximumPoolSize()) { return false; } return super.offer(o); }
  • 只有当前线程数大于核心线程数、小于最大线程数,并且已提交的任务个数大于当前线程数时,才会创建新的线程。

2.3 总结

Tomcat的线程池扩展了原生的ThreadPoolExecutor,并通过定制版的任务队列TaskQueue来控制线程的创建和任务的添加逻辑。整个线程池的处理逻辑如下:

  • 前corePoolSize个任务,每来一个任务就创建一个新线程。
  • 后续的任务会被添加到任务队列中,让所有线程去抢。如果已提交的任务大于当前线程数量,则会创建临时线程,直到线程数达到最大线程。
  • 如果队列满了(达到了最大线程数量后,继续添加任务到队列导致),执行了拒绝策略。则继续尝试把任务添加到任务队列。
  • 如果再次添加队列也失败,执行拒绝策略。

参考资料

  1. Tomcat如何扩展Java线程池 - 掘金
  2. [tomcat对JUC线程池的扩展 - 知乎](https://zhuanlanTomcat如何扩展Java线程池 =================

Tomcat是一个常用的Java Web服务器,它使用了自定义的线程池来处理请求。在Tomcat中,可以通过定制化的方式来扩展Java线程池,以满足特定的业务需求。

  1. Java线程池

Java线程池是通过ThreadPoolExecutor类来实现的。它的创建参数包括核心线程数、最大线程数、线程空闲时间、任务队列等。Java线程池的处理逻辑如下:

  • 前corePoolSize个任务,每来一个任务就创建一个新线程。
  • 后面的任务会被添加到任务队列中,等待线程池中的线程来执行。
  • 如果任务队列已满,且线程数还未达到最大线程数,会创建临时线程来执行任务。
  • 如果线程数已达到最大线程数,再次提交任务会执行拒绝策略。
  1. Tomcat线程池

Tomcat的线程池是基于ThreadPoolExecutor的定制版本,它需要限制线程个数和队列长度,以避免资源耗尽的风险。Tomcat构建线程池的代码如下:

TaskQueue taskqueue = new TaskQueue(); TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-", daemon, getThreadPriority()); executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS, taskqueue, tf);

Tomcat定制了任务队列和线程工厂,并设置了核心线程数和最大线程数来限制线程数量。

  • Tomcat的任务队列是TaskQueue,它是对Java的LinkedBlockingQueue的扩展。TaskQueue重写了offer方法,用于控制任务的添加逻辑,以实现弹性创建线程的需求。
  • Tomcat的线程工厂是TaskThreadFactory,它可以对创建的线程进行重新命名。
  1. 总结

Tomcat通过定制化的方式扩展了Java线程池,以满足特定的业务需求。它通过定制的任务队列和线程工厂来限制线程个数和队列长度,并通过重写execute方法来实现自己的任务处理逻辑。Tomcat的线程池处理流程如下:

  • 前corePoolSize个任务,每来一个任务就创建一个新线程。
  • 后面的任务会被添加到任务队列中,让所有线程去抢。如果队列已满,会创建临时线程。
  • 如果线程数达到最大线程数,继续尝试将任务添加到任务队列。
  • 如果再次添加队列失败,执行拒绝策略。

Learn more:

  1. Tomcat如何扩展Java线程池 - 掘金
  2. tomcat对JUC线程池的扩展 - 知乎
  3. 浅谈可扩展线程池 | 青空之蓝

本文作者:yowayimono

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!