了解 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 的线程转储的主要内容,如果未能解决你的问题,请参考以下文章
apache http server 和 tomcat是啥关系
十分不解,启动tomcat后实现了ServletContextListener的类的contextInitialized()方法执行了2次