【问题标题】:reason of why number of Java threads growing in timeJava线程数量随时间增长的原因
【发布时间】:2018-08-17 09:36:50
【问题描述】:

我有一个独立的 Java 控制台程序,它在生产中使用大约 80-170(160 是平均负载下的典型数字)线程。项目中部分代码被替换,功能正常,但启动程序后线程数不断增长。 当虚拟机几乎崩溃时,我意识到了这个问题。然后它有 30.000 个线程。

我想在生产环境中找到这种行为的原因,所以如果有任何有用的工具,它必须是命令行程序或者应该能够从远程主机运行。

我用 'ps huH p | 检查了它。 wc -l' 命令和 VisualVm 程序。不幸的是,VisualVm 远程仅提供有关线程号的信息,“线程”选项卡未处于活动状态

我试图从 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)

我不明白它们是什么。

你能帮我找出什么代码一次又一次地创建新线程吗?有什么好工具吗?

谢谢!

【问题讨论】:

  • 有用的工具: 调试器。它将显示您的所有线程,并可以暂停它们,以便您可以查看调用堆栈并单步执行代码以查看它在做什么。如果您不想连接调试器,只需获取thread dump。 --- 如果您知道新线程在做什么,您应该能够弄清楚它们首先启动的原因。
  • 这是一个庞大的、单一的、多线程的应用程序,难以调试。关于线程转储,我更新了我的描述。
  • 我阅读了随附的答案,我认为它不在这里。问题不在于我如何进行线程转储,而在于我如何找到创建上述线程的人,或者我应该识别哪些模式,或者只是获取在过去 x 秒内创建的线程。

标签: java multithreading jvm profiler java-threads


【解决方案1】:

JProfiler 中的线程监视器视图可以向您显示创建任何线程的堆栈跟踪,只要 CPU 记录处于活动状态。

免责声明:我公司开发 JProfiler。

【讨论】:

  • 谢谢!我自己解决了这个问题,这是编程错误。但如果没有它,我就不会知道 JProfiler。我在自己的电脑上试了一下,觉得这东西很棒!很好,您正在开发这样的产品。
【解决方案2】:

我会说jstack 是完成此类任务的正确工具。您可以通过堆栈跟踪和源代码了解线程的性质。 例如。 at java.util.TimerThread.mainLoop(Timer.java:526) 表示您的代码使用Timer 类,并且它的线程正在等待下一个计划。 java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074) 表示您使用ExecutorService 实现之一,其工作线程正在等待下一个任务。尝试分析有多少线程池线程处于活动状态以及原因,可能它们是您的问题的根源。

【讨论】:

  • 用jstack,我发现了问题。日志显示了许多由 timertasks 创建的线程。
  • 很高兴听到 :)
猜你喜欢
  • 2017-03-11
  • 2016-07-04
  • 1970-01-01
  • 2014-04-27
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多