2014-08-29 69 views
2

在我们的AppServer中,我们看到线程计数超过了其JMX线程数阈值(最大值= 500,实际值= 595)。运行的线程太多

我看到没有死锁。我已经采取了线程转储,并看到了595个的线程,其中大多数落入两类:

1)234的线程在定时等待(如下所示线程转储)

"Timer-232" daemon prio=10 tid=0x00007f46c85cd000 nid=0x7b06 in Object.wait() [0x00007f4668001000] 
    java.lang.Thread.State: TIMED_WAITING (on object monitor) 
     at java.lang.Object.wait(Native Method) 
     - waiting on <0x000000075246c498> (a java.util.TaskQueue) 
     at java.util.TimerThread.mainLoop(Timer.java:509) 
     - locked <0x000000075246c498> (a java.util.TaskQueue) 
     at java.util.TimerThread.run(Timer.java:462) 

2)233处于等待状态的线程(如下所示的线程转储)。我猜这是队列中被阻塞的罪魁祸首,特别是延迟队列。

"AsyncHttpClient-Reaper" daemon prio=10 tid=0x00007f469cd4c000 nid=0x7b09 waiting on condition [0x00007f4667cfe000] 
    java.lang.Thread.State: WAITING (parking) 
     at sun.misc.Unsafe.park(Native Method) 
     - parking to wait for <0x00000007524a2908> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) 
     at java.util.concurrent.locks.LockSupport.park(LockSupport.java:156) 
     at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1987) 
     at java.util.concurrent.DelayQueue.take(DelayQueue.java:160) 
     at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:609) 
     at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:602) 
     at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:947) 
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907) 
     at java.lang.Thread.run(Thread.java:662) 

你能帮我理解是什么导致线程超过JMX阈值?这是我第一次使用线程场景,因此无法进行稳定的分析。提前致谢。

+0

看起来你正在你的线程中运行长时间的工作,并且发布了越来越多的工作。 – 2014-08-29 14:41:12

+0

答案很简单:您创建的线程太多。听起来很明显,但事实确实如此。分析的方式可以是每当你开始一个新线程时查看,看看造成最多线程的是什么。或者检查一下你是否可以找出这些线程正在做什么以及它们为什么没有完成...... – WarrenFaith 2014-08-29 14:41:55

+0

正如斯图尔特所建议的那样,如果你能做到,学习Java的'Executors'和'ThreadPool'概念并重写那些部分应用程序。 – watery 2014-08-29 23:13:53

回答

2

看起来像是你的系统有太多的异步请求。调整它们或设置这些请求的最大池数

+0

感谢您对咖啡的见解。我看到的一件奇怪的事情是它只发生在一台服务器上。我们有8台服务器的应用程序。但是,为什么这只发生在一台服务器上。我们在所有服务器上都有相同的-xmx和-xms。 – 2014-09-02 18:14:44

+0

到目前为止,我们很难说清楚。它可能是服务器亲和力,较差的负载平衡(如果它们在相同的环境中),网络怪癖,不同的硬件/虚拟机规格等。我将着手研究的几件事是看看一台应用程序服务器与其他服务器相比收到多少请求以及查看CPU使用情况。也许测试服务器上的响应时间与其他服务器相比,看看您是否看到响应时间较慢。基本上任何迹象表明,该服务器上发生的事情正在发生,而其他人没有发生 – coffeeaddict 2014-09-02 18:24:23

2

您的一半线程是java.util.TimerThread的实例。只要有东西创建了java.util.Timer的实例,就会创建此线程的实例;每个Timer实例创建它自己的线程。

看起来像是计时器线程处于等待执行TimerTask之前的特定时间段过去的状态。由于有很多定时器线程,因此可能是代码中有一些地方每次要安排TimerTask时都会创建新的Timer实例。这将最终创建与未完成任务一样多的线程,这可能相当浪费。

如果要运行的任务是短暂且可靠的,它们可以共享一个Timer实例。

但是,如果任务长时间运行,则可能会延迟执行后续任务。或者,如果任务引发未捕获的异常,它将取消计时器线程并阻止后续任务被执行。如果其中任何一种可能,您应该使用Executors.newScheduledThreadPool创建一个单独的ScheduledExecutorService并在其上计划任务,而不是创建新的Timer实例。

+0

谢谢Stuart对此有所洞察。我看到的一件奇怪的事情是它只发生在一台服务器上。我们有8台服务器的应用程序。但是,为什么这只发生在一台服务器上。我们在所有服务器上都有相同的-xmx和-xms。 – 2014-09-02 18:15:24