查看占用 CPU 最多的 Java 线程

示例代码如下,主线程不断做运算来占用 CPU,其余线程只阻塞,不做其他事:

public class Hello {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread() {
                public void run() {
                    try {
                        Thread.sleep(100000);
                    } catch(Exception e) {}
                }
            }.start();
        }

        Thread t = new Thread() {
                public void run() {
                    int i = 0;
                    while (true) {
                        i = (i++) / 100;
                    }
                }
            };

        t.setName("test threads");
        t.start();
    }
}

编译,运行。先找到 Java 的进程:

$ ps ux | grep java
lu4nx    19878  112  0.1 8049880 32016 pts/1   Sl+  15:11   0:03 java Hello

再查看它内部线程的运行情况:

$ top -Hp 19878
19912 lu4nx     20   0 8049880  32016  17620 R 99.3  0.2   0:21.81

如上,PID 19912 占用大量的 CPU 资源。

接下来用 jstack 来查看 Java 的堆栈信息:

$ jstack 19912

因为 jstack 输出的内部线程号是十六进制的,所以先把 19912 转成 16 进程表示:

$ python3 -c 'print(hex(19912))'
0x4dc8

然后再到输出的栈信息中找到线程 0x4dc8 的信息,如:

"test threads" #21 prio=5 os_prio=0 tid=0x00007fa7502c1000 nid=0x4dc8 runnable [0x00007fa6e2c1f000]
   java.lang.Thread.State: RUNNABLE
        at Hello$2.run(Hello.java:17)

表示 0x4dc8 线程在执行 Hello.java 第 17 行代码。