При получении дампа потока сервера Tomcat, который в основном простаивает, многие потоки могут отображаться в состоянии RUNNABLE, например:
"http-bio-8443-exec-21975" daemon prio=10 tid=0x00007f6f6406c000 nid=0x222a runnable [0x00007f6f156ae000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at org.apache.coyote.http11.InternalInputBuffer.fill(InternalInputBuffer.java:516)
at org.apache.coyote.http11.InternalInputBuffer.fill(InternalInputBuffer.java:501)
at org.apache.coyote.http11.Http11Processor.setRequestLineReadTimeout(Http11Processor.java:173)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:924)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:565)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309)
- locked <0x00000007cadcd3f8> (a org.apache.tomcat.util.net.SocketWrapper)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:662)
Моя интерпретация исходного кода заключается в том, что этот поток ожидает (с тайм-аутом) дополнительных данных от HTTP-поддержки соединения. Таким образом, несмотря на то, что поток RUNNABLE, он не потребляет процессор.
Thread.State RUNNABLE javadoc говорит:
Поток в рабочем состоянии выполняется на виртуальной машине Java, но может ожидать других ресурсов от операционной системы, таких как процессор.
Таким образом, в этом случае этим другим ресурсом будет ввод-вывод вместо ЦП.
В другом вопросе Java socketRead0 Issue, Джефф отвечает:
Я считаю, что когда вы используете нативный метод Java, трассировка стека будет указывать RUNNABLE, даже если вызов фактически заблокирован в ожидании какого-либо события. По сути, я не верю, что у Java есть какой-либо способ узнать, что на самом деле делает собственный метод, поэтому он помечает эти вызовы как RUNNABLE. Я видел это с помощью socketRead0() и socketAccept(), которые обычно блокируются.
Я пришел к аналогичным выводам, и я хотел бы проверить эту интерпретацию в этом специальном вопросе, а именно:
Если я хочу проанализировать использование ЦП, просматривая ВЫПОЛНЯЕМЫЕ потоки, мне, возможно, придется исключить потоки в собственных методах, внимательно изучив их исходный код?
Дело в том, что это не так просто, как смотреть только на состояние потока, а скорее копаться в исходном коде и начинать догадываться, что может делать конкретный нативный метод (или даже смотреть на его исходный код C или C++).