当前位置: 首页 > 知识库问答 >
问题:

线程转储包含处于RUNNABLE状态的线程,没有堆栈

司徒墨竹
2023-03-14

在使用CPU的高负载应用程序上进行线程转储,我看到很多线程处于这种状态:

“ajp executor threads-XXXXXX”prio=10 tid=0x00002b04b8b33801 nid=0x5327可运行[0x0000000000000000]java。lang.Thread。状态:可运行

对我来说,真正奇怪的是根本没有堆栈跟踪,ajp线程的总数高于配置的最大线程数(见下文)

当应用程序在以下平台上运行时会发生这种情况:

  • JBoss 7
  • Java 7u75
  • 红帽5.11
  • 在VMWare Enterprise/vSphere 5.5上运行

执行人的配置为:

 <subsystem xmlns="urn:jboss:domain:threads:1.1">
        <bounded-queue-thread-pool name="ajp-executor">
            <core-threads count="32"/>
            <queue-length count="1"/>
            <max-threads count="300"/>
            <keepalive-time time="5" unit="seconds"/>
        </bounded-queue-thread-pool>
    </subsystem>

请注意,此主机上的负载非常高:

>

  • CPU达到70%

    负载为4(=vCPU数量)

    请注意,这些线程不是空闲线程,因为空闲线程具有以下堆栈跟踪:

     "Reference Handler" daemon prio=5 tid=0x00007f92cb00e800 nid=0x3703 in Object.wait() [0x000000012057e000]
         java.lang.Thread.State: WAITING (on object monitor)
         at java.lang.Object.wait(Native Method)
         - waiting on <0x00000007aaa84470> (a java.lang.ref.Reference$Lock)
         at java.lang.Object.wait(Object.java:503)
         at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
         - locked <0x00000007aaa84470> (a java.lang.ref.Reference$Lock)
    
  • 共有2个答案

    苏鹏鹍
    2023-03-14

    这些是AJP执行器连接池中的空闲线程。您已经将核心线程设置为32,这意味着连接池将始终保持32个线程,尽管它们可能处于空闲状态。通过您的配置,您可以看到多达300个线程,但任何超过32个的线程在消亡并从连接池中删除之前只需等待5秒。

    至于CPU负载,我怀疑它与这些空闲连接池线程有任何关系。

    有关连接池和keep alive的更多信息,请参阅John Skeet的回答:https://stackoverflow.com/a/10379348/91866

    魏勇军
    2023-03-14

    经过进一步分析,我发现该问题是由于通过以下方式启用了远程调试:

    -X运行jd wp:传输=dt_socket,服务器=y,暂停=n,地址=XXXX XXX

    这解释了线程转储中这些奇怪的空堆栈跟踪。

     类似资料:
    • 我已经用Java编写了一个简单的ECHO协议服务器,使用。 很简单: 线程正在上等待客户端的输入。但是我发现所有的工作线程都处于状态,通过,我认为它们可能处于状态。 线程在等待数据到达时被阻塞,但为什么在这里它是可运行的? 下面是输出:

    • 问题内容: 我试图在这里理解代码,特别是匿名类 文章说 处理程序将更新代码作为主线程的一部分运行,从而避免了第二个线程的开销。 创建新的Runnable类是否应该创建新的第二个线程?除了能够将Runnable类传递给postAtTime之外,这里Runnable类的目的是什么? 谢谢 问题答案: 通常用于提供线程应运行的代码,但它本身与线程无关。它只是一个带有方法的对象。 在Android中,该类

    • 用例:每次我需要处理一个作业时创建一个新线程。 目前的实现:我使用的执行器服务与固定大小的线程池,例如50。对于每个作业,我都向executor服务提交一个新线程。 我试图实现的行为更像是自动伸缩。在高峰时间跨越更多的服务器(在本例中是线程)。并在负载不是很高的时候终止额外的服务器并保持最小的服务器计数。

    • 问题内容: 我正在尝试转储所有活动线程的列表,包括每个线程的当前堆栈。我可以使用threading.enumerate()获得所有线程的列表,但是我不知道从那里到堆栈的方法。 背景:Zope / Plone应用程序有时会出现故障,消耗100%的cpu,需要重新启动。我觉得这是一个循环,无法正常终止,但是我无法在test- environemt中重现该循环以进行验证。我设法注册了可以从外部触发的信号

    • 我们在其中一个模块中使用了Hystrix-断路器模式[library]。usecase是:-我们正在从kafka轮询16个消息,并使用pararllel流处理它们,因此,对于工作流中的每条消息,它需要3个rest调用,这些调用由hystric命令保护。现在,问题是当我尝试运行单个实例时,CPU显示尖峰,线程转储显示许多线程处于等待状态,等待所有3个命令。如下所示:-

    • 有人能给我解释一下VisualVM中、、和线程状态之间的区别吗。 这是我发现的: :线程仍在运行 :线程正在Hibernate(对线程对象调用了方法yield()) :线程被互斥锁或屏障阻止,正在等待另一个线程释放锁 :停止的线程被暂停,直到获得许可。解压线程通常是通过调用线程对象上的方法unpark()来完成的。 :线程正在等待条件变为true以恢复执行 我无法理解的是州立公园,到底是什么让这条