2014-08-29 119 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