为什么空闲的Java线程显示高CPU使用率?

4

我正在使用安装了JDK 8的Amazon Linux上的Wildfly 11。 我试图弄清楚为什么一个据说在等待的线程显示高CPU使用率。 我像这样获取了我的应用程序服务器进程的PID

[jboss@prodmachine ~]$ ps -elf | grep java
0 S jboss     8844     1  0  80   0 - 28275 wait   15:30 ?        00:00:00 /bin/sh /usr/java/wildfly/bin/standalone.sh -c standalone.xml
0 S jboss     8896  8844 99  80   0 - 7337773 futex_ 15:30 ?      08:16:14 /usr/java/default/bin/java -D[Standalone] -server -Xms64m -Xmx25600m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=1024m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman,com.newrelic -Djava.awt.headless=true -javaagent:/usr/java/wildfly/newrelic/newrelic.jar -Dorg.jboss.boot.log.file=/usr/java/wildfly/standalone/log/server.log -Dlogging.configuration=file:/usr/java/wildfly/standalone/configuration/logging.properties -jar /usr/java/wildfly/jboss-modules.jar -mp /usr/java/wildfly/modules org.jboss.as.standalone -Djboss.home.dir=/usr/java/wildfly -Djboss.server.base.dir=/usr/java/wildfly/standalone -c standalone.xml

然后我查看了与此相关的高CPU使用率进程

top -n 1 -H -p 8896

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                           
 9310 jboss     20   0 28.0g 4.4g  33m S 43.3 15.2   3:16.72 java                                                                               
 9207 jboss     20   0 28.0g 4.4g  33m S 13.8 15.2  42:00.05 java                                                                               
 9292 jboss     20   0 28.0g 4.4g  33m S 13.8 15.2   3:17.87 java

"9310"的十六进制为"0x245e",当我使用jstack进行线程转储时,就是在寻找这个值...

[jboss@prodmachine ~]$ /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.181-8.b13.39.39.amzn1.x86_64/bin/jstack -l 8896 > /tmp/jstack.txt

揭示了这个。
"default task-86" #272 prio=5 os_prio=0 tid=0x00000000090ee800 nid=0x245e waiting on condition [0x00007f3220cee000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x0000000181c9e050> (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)

但是我读到的所有资料都表明,“等待”状态的线程不应占用任何CPU资源。那么为什么我会看到这种奇怪的结果呢?我在路上搞错了什么吗?


2
“park” 表示线程被挂起,没有使用 CPU。难道没有可运行的线程吗?此外,请查看堆并查看 GC 是否频繁移动。基本上,没有足够的信息来确定您的问题是什么。 - John Vint
1个回答

1

不要使用命令行来监视线程活动,使用Java Visual VM会更好,极大地帮助您。

在“WAITING”或“SLEEPING”状态下的线程是否使用CPU?

进入和退出睡眠/等待状态需要时间。这个成本相对较小,但如果调用次数足够多,则不可忽略。

在wait()的情况下,它可能会出现虚假唤醒,因此如果您在循环中使用它,这理论上可能会消耗大量CPU。在实践中,根据我的经验,这种情况很少发生,但如果您忘记使用循环,它可能会创建难以重现的错误。


Java Visual VM位于JDK 1.8文件夹下,按照以下路径执行:jdk1.8.x => bin => jvisualvm.exe - Ikbel
我们正在使用Amazon Linux,并且仅具有SSH访问权限。除非我对shell有所误解,否则视觉效果不是一个简单的选项。 - Dave

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接