了解 Apache Tomcat 6.0.26 的线程转储

Posted

技术标签:

【中文标题】了解 Apache Tomcat 6.0.26 的线程转储【英文标题】:Understanding Thread Dump of Apache Tomcat 6.0.26 【发布时间】:2013-01-05 18:29:16 【问题描述】:

我做了一个观察,我想完全理解它。

首先,我定期进行线程转储并创建线程状态摘要:

jstack -l 19498 > dump.txt ; awk '/State: /  print ' < dump.txt  | sort | uniq -c

上面命令的结果是这样的:

 70    java.lang.Thread.State: RUNNABLE
  8    java.lang.Thread.State: TIMED_WAITING (on object monitor)
  1    java.lang.Thread.State: TIMED_WAITING (sleeping)
171    java.lang.Thread.State: WAITING (on object monitor)

RUNNABLE = 实际处理 Web 应用程序的请求TIMED_WAITING = Quartz 调度程序线程WAITING = 等待处理即将到来的 HTTP 请求的空闲线程

WAITING 线程示例(所有 WAITING 看起来像这样):

"http-80-178" daemon prio=10 tid=0x00007fa8c0bbe000 nid=0x2e11 in Object.wait() [0x00007fa8aaae9000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00007fa8e6b873c8> (a org.apache.tomcat.util.net.JIoEndpoint$Worker)
        at java.lang.Object.wait(Object.java:485)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.await(JIoEndpoint.java:458)
        - locked <0x00007fa8e6b873c8> (a org.apache.tomcat.util.net.JIoEndpoint$Worker)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:484)
        at java.lang.Thread.run(Thread.java:619)

   Locked ownable synchronizers:
        - None

Tomcat 配置

我的Tomcat配置参数都是使用默认值,意思是

minSpareThreads = 25(因此 Tomcat 确保有 25 个线程准备好处理 maxThreads = 200(200 个请求可以在没有警告的情况下并行处理)acceptCount = 100(如果所有 200 个线程都忙,HTTP 连接器可以将额外的 100 个请求排队)

问题

当我定期执行命令时,我看到线程总数在增加。没有BLOCKING 线程。

我不明白为什么线程数在增加,因为有很多线程处于WAITING 状态,准备处理另一个 HTTP 请求。

我还看到RUNNABLE + WAITING 在一段时间内(例如 1 小时)保持不变,但随后增加 5 或 6 并再次保持不变。好像线程池越来越大,直到达到极限,Tomcat关闭了……

TIMED_WAITING 线程很可能来自运行在同一个 JVM 中的 Quartz 调度程序。

我对值的解释不正确吗?

【问题讨论】:

【参考方案1】:

你读过this article吗?引用一小章:

由于 java ThreadPoolExecutor 的 FIFO 行为,每个 线程至少会在“maxIdleTime”之前等待一个新任务 有资格关闭。此外,再次因为 FIFO 线程池的行为,对于要关闭的线程,它是必需的 至少等于 maxIdleTime 的时间段在没有 ANY 的情况下过去了 请求进来

【讨论】:

是的,我找到了那篇文章。所以我想知道为什么会这样设计……FILO 策略会更好,不是吗?但是,最后一句话并不清楚:“要关闭线程,需要至少等于 maxIdleTime 的时间段没有任何请求进入”。这是否意味着“针对此线程或一般针对任何线程的任何请求? 我也同意这篇文章。 Wish 有更多时间亲自尝试线程池并尝试建议的 LIFO/FILO 选项。据我了解,他谈到了对任何线程的请求。但不要相信我的话 - 测试一下,让我们都知道!

以上是关于了解 Apache Tomcat 6.0.26 的线程转储的主要内容,如果未能解决你的问题,请参考以下文章

tomcat有没有运行成功如何查看

apache http server 和 tomcat是啥关系

Apache+Tomcat部署负载均衡(或集群)

十分不解,启动tomcat后实现了ServletContextListener的类的contextInitialized()方法执行了2次

tomcat 和 apache 整合后利用Tomcat 进行URL重写

Apache + Tomcat 部署中 Tomcat 线程池的行为