Tomcat 线程池

简介: Tomcat 线程池
概述

Tomcat 是一个流行的 Java Web 服务器,它使用线程池来处理客户端请求。线程池是一组预先创建的线程,用于执行并发任务,以提高性能和资源利用率。

在 Tomcat 中,线程池被用来处理传入的 HTTP 请求。当客户端发送请求时,Tomcat 会从线程池中获取一个可用的线程来处理该请求。处理完请求后,线程将返回线程池,并在下一个请求到来时再次被重用。

Tomcat 的线程池配置可以通过编辑 server.xml 文件来进行。以下是一些常见的线程池配置选项:

  1. maxThreads:指定线程池中的最大线程数。这决定了 Tomcat 能同时处理的最大请求数量。
  2. minSpareThreads:指定线程池中的最小空闲线程数。当请求量较小时,线程池中的线程数量可以减少到此值以下。
  3. maxIdleTime:指定线程在空闲状态下保持活动的最长时间。超过该时间后,线程将被终止并从线程池中移除。
  4. acceptCount:指定等待队列的最大长度。当所有线程都在忙碌时,新的请求将被放置在等待队列中。
tomcat线程池工作原理

Tomcat 的线程池工作原理如下:

  1. 初始化线程池:在 Tomcat 启动时,会初始化线程池,并创建一定数量的线程。
  2. 接收请求:当客户端发起请求时,Tomcat 的连接器将接收到请求,并将其传递给线程池。
  3. 线程池调度:线程池中的线程会被调度来处理请求。如果线程池中有空闲线程,将会有一个线程去执行该请求。如果线程池中没有可用线程,请求将进入等待队列。
  4. 请求处理:选中的线程会处理请求,包括解析请求、执行相应的业务逻辑等。该线程会一直处理请求直到完成。
  5. 请求完成:处理完请求后,线程将返回到线程池中,变为可用状态,以供处理下一个请求。
  6. 等待队列:如果线程池中没有空闲线程,新到达的请求将会进入等待队列。请求按照先到先服务的顺序排队等待处理。等待队列的长度由 acceptCount 参数决定。
  7. 线程重用:线程池中的线程会被重复使用,避免了频繁创建和销毁线程的开销。这样可以提高性能,并降低资源消耗。
  8. 线程管理:线程池还负责管理线程的生命周期,包括创建、销毁和维护线程的状态。

这里的空闲线程指 最大线程,即如果核心线程为2,最大线程为3,但现在来了3个任务,tomcat的线程池会创建一个救急线程来执行第三个任务,并不回加入队列。这个点跟普通线程池不一样。

总结:

提交任务数小于核心线程数,则创建任务数的线程;

当前线程数达到核心线程数,调用任务队列方法;

当前线程数达到最大线程数,默认放入任务队列;

提交任务数小于等于当前线程,表明还有空闲线程,无需创建线程;

提交任务数大于当前线程数小于最大线程数,重写任务队列的offer方法返回false不执行默认的放入队列操作,继续创建线程(false表示任务队列已满);

提交任务数达到任务队列最大值,执行拒绝策略。

关键源码
1. public void execute(Runnable command, long timeout, TimeUnit unit) {
2.  //这个字段是记录的线程提交的数量,如果线程执行完毕,这个字段会减1 
3.  submittedCount.incrementAndGet();
4.  try {
5.  //执行jdk的线程池代码
6.    super.execute(command);
7.  } catch (RejectedExecutionException rx) {
8.  //拒绝策略,发生的情况是线程超过最大值(maxThreads),并且队列也已经满了,也就是(Integer.MAX+maxThreads)
9.    if (super.getQueue() instanceof TaskQueue) {
10.       final TaskQueue queue = (TaskQueue)super.getQueue();
11.       try {
12.       //这里其实就是讲这个线程(60s后)丢到队列里面,如果60s后队列还是满的,那就没办法了,抛异常……
13.         if (!queue.force(command, timeout, unit)) {
14.           submittedCount.decrementAndGet();
15.           throw new RejectedExecutionException(sm.getString("threadPoolExecutor.queueFull"));
16.         }
17.       } catch (InterruptedException x) {
18.         submittedCount.decrementAndGet();
19.         throw new RejectedExecutionException(x);
20.       }
21.     } else {
22.       submittedCount.decrementAndGet();
23.       throw rx;
24.     } 
25.   }
26. }

TaskQueue.java

1. public boolean force(Runnable o, long timeout, TimeUnit unit) throws InterruptedException {
2. if ( parent.isShutdown() ) 
3. throw new RejectedExecutionException(
4. "Executor not running, can't force a command into the queue"
5.  );
6. //forces the item onto the queue, to be used if the task is rejected
7. return super.offer(o,timeout,unit); 
8. }
Connector 配置

Executor 线程配置

tomcat核心组件(题外)

它由多个核心组件组成,这些组件共同协作来实现对 Web 应用程序的处理和管理。以下是 Tomcat 的一些核心组件:

  1. 连接器(Connector):连接器负责接收客户端的 HTTP 请求,并将其传递给 Tomcat 进行处理。Tomcat 支持多种类型的连接器,如 HTTP 连接器、AJP(Apache JServ Protocol)连接器等。
  2. 引擎(Engine):引擎是 Tomcat 的顶层容器,它负责管理和协调多个虚拟主机(Host)的处理过程。每个引擎都有自己的生命周期和一组关联的虚拟主机。
  3. 虚拟主机(Host):虚拟主机用于托管多个 Web 应用程序。每个虚拟主机都有自己的域名或 IP 地址,并可以独立配置和管理自己的 Web 应用程序。
  4. 上下文(Context):上下文代表一个 Web 应用程序,它包含了应用程序的配置信息、Servlet、过滤器、监听器等。Tomcat 可以同时运行多个上下文,每个上下文都有唯一的上下文路径。
  5. Servlet 容器(Servlet Container):Servlet 容器负责加载、初始化和管理 Servlet。它提供了与 Servlet 相关的生命周期管理、请求处理和响应生成等功能。
  6. JSP 引擎(JSP Engine):JSP 引擎用于将 JSP(JavaServer Pages)文件转换为 Java 代码,并编译成 Servlet。Tomcat 使用 Jasper 作为默认的 JSP 引擎来处理 JSP 页面。
  7. 管理器(Manager):管理器负责管理和维护 Web 应用程序的会话(Session)。它可以跟踪会话的创建和销毁,以及提供会话的持久化和集群支持。

以上是 Tomcat 的一些核心组件,它们共同构成了 Tomcat 的基本架构,使其能够运行和管理 Java Web 应用程序。每个组件都承担着不同的职责和功能,相互配合,完成对 Web 应用程序的处理和服务。


相关文章
|
4天前
|
Java 应用服务中间件
Springboot启动的时候初始化的线程池默认配置tomcat
Springboot启动的时候初始化的线程池默认配置tomcat
22 1
|
7月前
|
Java 应用服务中间件
98分布式电商项目 - Tomcat性能优化(使用线程池)
98分布式电商项目 - Tomcat性能优化(使用线程池)
32 0
|
9月前
|
网络协议 Java 应用服务中间件
详解Tomcat的连接数与线程池,调优必备
详解Tomcat的连接数与线程池,调优必备
|
Java 应用服务中间件 Apache
Tomcat 线程池学习总结
Tomcat 线程池学习总结
418 0
|
Dubbo Java 应用服务中间件
每天都在用,但你知道 Tomcat 的线程池有多努力吗? (4)
每天都在用,但你知道 Tomcat 的线程池有多努力吗? (4)
100 0
|
监控 算法 Java
每天都在用,但你知道 Tomcat 的线程池有多努力吗? (3)
每天都在用,但你知道 Tomcat 的线程池有多努力吗? (3)
100 0
|
Java 应用服务中间件
每天都在用,但你知道 Tomcat 的线程池有多努力吗? (2)
每天都在用,但你知道 Tomcat 的线程池有多努力吗? (2)
216 0
|
Java 应用服务中间件 程序员
每天都在用,但你知道 Tomcat 的线程池有多努力吗? (1)
每天都在用,但你知道 Tomcat 的线程池有多努力吗? (1)
116 0
|
监控 Java 应用服务中间件
美团动态线程池思路开源框架(DynamicTp),动态调整Tomcat、Jetty、Undertow线程池参数篇
大家好,这篇文章我们来介绍下动态线程池框架(DynamicTp)的adapter模块,上篇文章也大概介绍过了,该模块主要是用来适配一些第三方组件的线程池管理,让第三方组件内置的线程池也能享受到动态参数调整,监控告警这些增强功能。
722 1
美团动态线程池思路开源框架(DynamicTp),动态调整Tomcat、Jetty、Undertow线程池参数篇
|
安全 Dubbo Java
原生线程池这么强大,Tomcat 为何还需扩展线程池?
Tomcat/Jetty 是目前比较流行的 Web 容器,两者接受请求之后都会转交给线程池处理,这样可以有效提高处理的能力与并发度。JDK 提高完整线程池实现,但是 Tomcat/Jetty 都没有直接使用。Jetty 采用自研方案,内部实现 QueuedThreadPool 线程池组件,而 Tomcat 采用扩展方案,踩在 JDK 线程池的肩膀上,扩展 JDK 原生线程池。 JDK 原生线程池可以说功能比较完善,使用也比较简单,那为何 Tomcat/Jetty 却不选择这个方案,反而自己去动手实现那?
原生线程池这么强大,Tomcat 为何还需扩展线程池?