快速定位JVM中消耗CPU最多的线程
从哪里看来的,忘记了!!!
在日常 Java 的开发中,性能调优肯定是很多人不能绕开的一个环节。而其中最简单,也是最基础的一个问题就是如何定位消耗 CPU 最多的线程。
例子的代码具体如下
public class Test {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(100 * 1000);
} catch (Exception e) {
}
}
}).start();
}
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while (true) {
i = (i++) / 100;
}
}
});
thread.setName("busyness");
thread.start();
System.out.println("start...");
}
}
这个例子里新创建了 11 个线程,其中 10 个线程没干什么事,主要是 sleep,另外有一个线程在循环里一直跑着,可以想象这个线程是这个进程里最耗 CPU 的线程了,那怎么把这个线程给抓出来呢?
首先我们可以通过top找到最消耗CPU的进程

通过以上这个结果,我们可以看到 cpu 最高的线程是 pid 为 15641的线程,占了CPU是100% ,
我们可以通过top -Hp <pid>来看这个进程里所有线程的 CPU 消耗情况,得到类似下面的数据。

可以看到 cpu 最高的线程是 pid 为 15661的线程,占了 99.3%:
将15661转化为16进制:
[root@localhost ~]# printf "%x\n" 15661
3d2d
然后执行 jstack -l pid 这里的pid 是进程的pid 比如上面的15664
[root@localhost ~]# jstack -l 15641
2018-07-21 19:46:27
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.131-b11 mixed mode):
"Attach Listener" #20 daemon prio=9 os_prio=0 tid=0x00007f1cec001000 nid=0x3d60 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"DestroyJavaVM" #19 prio=5 os_prio=0 tid=0x00007f1d14008800 nid=0x3d1a waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"busyness" #18 prio=5 os_prio=0 tid=0x00007f1d1411f000 nid=0x3d2d runnable [0x00007f1d18530000]
java.lang.Thread.State: RUNNABLE
at com.java8.demo.Test$2.run(Test.java:26)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"Service Thread" #7 daemon prio=9 os_prio=0 tid=0x00007f1d140e2000 nid=0x3d21 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C1 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007f1d140d7000 nid=0x3d20 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007f1d140d5000 nid=0x3d1f waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007f1d140d3800 nid=0x3d1e runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f1d140a0800 nid=0x3d1d in Object.wait() [0x00007f1d19540000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000e4a08ec8> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
- locked <0x00000000e4a08ec8> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
Locked ownable synchronizers:
- None
"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007f1d1409b800 nid=0x3d1c in Object.wait() [0x00007f1d19641000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000e4a06b68> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
- locked <0x00000000e4a06b68> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
Locked ownable synchronizers:
- None
"VM Thread" os_prio=0 tid=0x00007f1d14094000 nid=0x3d1b runnable
"VM Periodic Task Thread" os_prio=0 tid=0x00007f1d140e5000 nid=0x3d22 waiting on condition
JNI global references: 9
上面的线程栈我们注意到 nid 的值其实就是线程 ID,它是十六进制的, 标识红色的nid编号就是我们要找的最终线程。

浙公网安备 33010602011771号