Анализ 90% потоков в java.lang.Thread.State: WAITING (парковка)

Количество потоков на моем сервере приложений tomcat растет каждый день.

Когда я взял дамп потока для анализа.

Я обнаружил, что из 430 потоков 307 потоков имеют этот статус.

Пример stacktrace

"pool-283-thread-1" #2308674 prio=5 os_prio=0 tid=0x000000000a916800 nid=0x1101 waiting on condition [0x00002aec87f17000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x00000006d9929ec0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
    at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
    at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
    - None

"pool-282-thread-1" #2307106 prio=5 os_prio=0 tid=0x000000000a4fb000 nid=0x78e3 waiting on condition [0x00002aec87e16000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x00000006d8ca7bf8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
    at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
    at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
    - None

Окружающая среда

JDK: jdk1.8.0_60
OS: Linux
Tomcat: tomcat-7.0.65

Не уверен, что это вызывает проблему.

Оцените любую помощь по этому вопросу.

Ответ 1

Это типичная утечка ресурсов. Вы используете какой-то ExecutorService где-то в своем приложении, и вы не закрываете этот пул после того, как работа завершена, заставляя потоки ждать навсегда.

Вы должны позвонить ExecutorService#shutdown(), чтобы закрыть пул и освободить/завершить его потоки после завершения работы.

Имена тем, такие как pool-282-thread-1 pool-283-thread-1, предполагают, что вы, скорее всего, используете однопользовательский пул (потому что номер пула большой, а нить - только 1). Идея ExecutorService состоит в том, чтобы повторно использовать потоки, которые не работают, чтобы выполнить еще одну работу. Поэтому при создании нового ExecutorService каждый раз, когда вам нужно выполнить какую-либо фоновую работу, вам следует скорее поделиться одним экземпляром и использовать его в своем приложении.