快速定位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编号就是我们要找的最终线程。

 

  

posted @ 2018-07-24 09:05  南极山  阅读(2182)  评论(0)    收藏  举报