Java 线程数量随时间增长的原因
reason of why number of Java threads growing in time
我有一个独立的 Java 控制台程序,它在生产中使用大约 80-170(160 是平均负载下的典型数字)线程。项目中替换了部分代码,功能正常,但启动程序后线程数不断增加。
当虚拟机几乎崩溃时,我意识到了这个问题。然后它有 30.000 个线程。
我想在生产环境中找到这种行为的原因,所以如果有任何有用的工具,它必须是命令行程序或者应该能够从远程主机 运行。
我用 'ps huH p | wc -l' 命令和 VisualVm 检查了它 program.Unfortunately VisualVm 远程仅提供有关线程号的信息,"Thread" 选项卡未激活
我试图从 jstack 命令获取有用的信息,但我无法从
中找到创建等的新线程是什么
"Timer-459" #1864 daemon prio=10 os_prio=0 tid=0x0bb6c400 nid=0x3c4f in Object.wait() [0x2a980000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at java.util.TimerThread.mainLoop(Timer.java:526)
- locked <0x4d18bc80> (a java.util.TaskQueue)
at java.util.TimerThread.run(Timer.java:505)
或
"pool-133-thread-2" #1877 prio=5 os_prio=0 tid=0x42a2c400 nid=0x3e5e waiting on condition [0x2b118000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x4d18ae80> (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:1074)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
我不明白它们是什么。
你能帮我找出什么代码一次又一次地创建新线程吗?有什么好的工具吗?
谢谢!
我会说 jstack
是完成此类任务的正确工具。您可以通过线程堆栈跟踪和源代码了解线程的本质。
例如。 at java.util.TimerThread.mainLoop(Timer.java:526)
表示您的代码使用 Timer
class 并且其线程正在等待下一个调度。 java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
表示您使用 ExecutorService
实现之一,其工作线程正在等待下一个任务。尝试分析有多少线程池线程处于活动状态以及原因,可能它们是您问题的根源。
只要 CPU 记录处于活动状态,JProfiler 中的线程监视器视图就可以向您显示创建任何线程的堆栈跟踪。
免责声明:我公司开发了 JProfiler。
我有一个独立的 Java 控制台程序,它在生产中使用大约 80-170(160 是平均负载下的典型数字)线程。项目中替换了部分代码,功能正常,但启动程序后线程数不断增加。 当虚拟机几乎崩溃时,我意识到了这个问题。然后它有 30.000 个线程。
我想在生产环境中找到这种行为的原因,所以如果有任何有用的工具,它必须是命令行程序或者应该能够从远程主机 运行。
我用 'ps huH p | wc -l' 命令和 VisualVm 检查了它 program.Unfortunately VisualVm 远程仅提供有关线程号的信息,"Thread" 选项卡未激活
我试图从 jstack 命令获取有用的信息,但我无法从
中找到创建等的新线程是什么"Timer-459" #1864 daemon prio=10 os_prio=0 tid=0x0bb6c400 nid=0x3c4f in Object.wait() [0x2a980000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at java.util.TimerThread.mainLoop(Timer.java:526)
- locked <0x4d18bc80> (a java.util.TaskQueue)
at java.util.TimerThread.run(Timer.java:505)
或
"pool-133-thread-2" #1877 prio=5 os_prio=0 tid=0x42a2c400 nid=0x3e5e waiting on condition [0x2b118000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x4d18ae80> (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:1074)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
我不明白它们是什么。
你能帮我找出什么代码一次又一次地创建新线程吗?有什么好的工具吗?
谢谢!
我会说 jstack
是完成此类任务的正确工具。您可以通过线程堆栈跟踪和源代码了解线程的本质。
例如。 at java.util.TimerThread.mainLoop(Timer.java:526)
表示您的代码使用 Timer
class 并且其线程正在等待下一个调度。 java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
表示您使用 ExecutorService
实现之一,其工作线程正在等待下一个任务。尝试分析有多少线程池线程处于活动状态以及原因,可能它们是您问题的根源。
只要 CPU 记录处于活动状态,JProfiler 中的线程监视器视图就可以向您显示创建任何线程的堆栈跟踪。
免责声明:我公司开发了 JProfiler。