Почему простаивающий поток Java показывает высокую загрузку процессора?
Я использую Wildfly 11 с JDK 8 на Amazon Linux. Я пытаюсь выяснить, почему поток, который якобы ожидает, показывает высокую загрузку процессора. Я получил 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)
но все, что я прочитал, указывает на то, что потоки в состоянии "ОЖИДАНИЕ" не должны занимать ресурсы ЦП. Так почему я вижу этот странный результат? Я что-то напортачил по пути?
1 ответ
Вместо использования командной строки для отслеживания активности потоков, используйте визуальную виртуальную машину Java, она намного лучше и очень поможет вам.
Используют ли потоки в состоянии "ОЖИДАНИЕ" или "ОЖИДАНИЕ" ЦП?
Есть время, необходимое для входа и выхода из режима ожидания / сна. Это сравнительно небольшая стоимость, но если ее назвать достаточно нетривиально.
В случае wait() он может внезапно пробуждаться, поэтому, если вы используете его в цикле, как это идиоматично, теоретически это может сжечь немного процессора. На практике это случается редко, по моему опыту, но достаточно часто, так что если вы забудете использовать цикл, это может создать трудности для воспроизведения ошибок.