如何找到占用CPU最高的是哪一个线程

当遇到CPU使用率飙升的问题时,本文介绍了一种定位占用CPU最高线程的方法。通过模拟程序创建多个线程,其中有一个线程持续运行导致CPU占用增加。通过`jps`、`top -Hp`、`printf`和`jstack -l`等命令,逐步找出并分析占用CPU最高的线程1。

一、需求分析

 

          经常听到朋友说他们线上CPU有时候突然飙升,想找到是哪个线程导致的,我相信他们肯定有自己的定位方法,今天我要分享的也仅仅是其中一种而已。


二、如何定位

      为了模拟这种现象,写一个程序,先看代码

  

public static void main(String[] args) {
		for(int i=1;i<=3;i++) {
			new Thread() {
	            @Override
				public void run() {
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}.start();
		}
		Thread thread = new Thread() {
			    @Override
				public void run() {
					while(true) {
						System.out.println("start foreach");
					}
				}
		};
		thread.setName("线程1");
		thread.start();
	}

      有几个线程,其中,有3个线程什么都没干,仅仅是sleep了,而另外一个单独的线程我让它while(true)一直不停的输出 "start foreach",很明显,这个线程名叫做"线程1"的线程肯定会大量占用CPU,那么在我们事先不知道的情况下,如何把它找出来呢?

      首先将上面代码打成一个jar包,然后直接启动即可,会看看源源不断的输出 start foreach,

      第一步:先jps看一下进程号

  

[root@slave ~]# jps
2942 Jps
2910 jar

      第二步:使用top -Hp  进程号  查看该进程下各个线程占用CPU情况

 

root@slave ~]# top -Hp 2910


top - 01:09:25 up 13 min,  2 users,  load average: 0.11, 0.13, 0.09
Tasks:  14 total,   0 running,  14 sleeping,   0 stopped,   0 zombie
Cpu(s):  5.1%us,  9.1%sy,  0.0%ni, 85.8%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   3907472k total,  1282472k used,  2625000k free,    69612k buffers
Swap:  1048572k total,        0k used,  1048572k free,   210764k cached

   PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                      
  2926 root      20   0 4048m 306m  11m S 11.7  8.0   0:16.61 java                         
  2910 root      20   0 4048m 306m  11m S  0.0  8.0   0:00.04 java                         
  2911 root      20   0 4048m 306m  11m S  0.0  8.0   0:00.46 java                         
  2912 root      20   0 4048m 306m  11m S  0.0  8.0   0:00.00 java                         
  2913 root      20   0 4048m 306m  11m S  0.0  8.0   0:00.00 java                         
  2914 root      20   0 4048m 306m  11m S  0.0  8.0   0:00.00 java                         
  2915 root      20   0 4048m 306m  11m S  0.0  8.0   0:00.00 java                         
  2916 root      20   0 4048m 306m  11m S  0.0  8.0   0:00.00 java                         
  2917 root      20   0 4048m 306m  11m S  0.0  8.0   0:00.00 java                         
  2918 root      20   0 4048m 306m  11m S  0.0  8.0   0:00.00 java                         
  2919 root      20   0 4048m 306m  11m S  0.0  8.0   0:00.45 java                         
  2920 root      20   0 4048m 306m  11m S  0.0  8.0   0:00.13 java                         
  2921 root      20   0 4048m 306m  11m S  0.0  8.0   0:00.00 java                         
  2922 root      20   0 4048m 306m  11m S  0.0  8.0   0:00.27 java 

     从上可以看到,线程号 2926的占用CPU最高。

     第三步: 执行 printf 0x%x 线程号 得到 此线程id的十六进制

  

[root@slave ~]# printf 0x%x 2926
0xb6e

    第四步:使用jstack -l 进程号 输出堆栈信息

  

[root@slave ~]# jstack -l 2910
2018-02-13 01:10:38
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.77-b03 mixed mode):

"Attach Listener" #14 daemon prio=9 os_prio=0 tid=0x00007f796402c000 nid=0xb9b runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"DestroyJavaVM" #13 prio=5 os_prio=0 tid=0x00007f799c009800 nid=0xb5f waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"线程1" #12 prio=5 os_prio=0 tid=0x00007f799c14c800 nid=0xb6e runnable [0x00007f7983849000]
   java.lang.Thread.State: RUNNABLE
        at java.io.FileOutputStream.writeBytes(Native Method)
        at java.io.FileOutputStream.write(FileOutputStream.java:326)
        at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
        at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
        - locked <0x000000008001d830> (a java.io.BufferedOutputStream)
        at java.io.PrintStream.write(PrintStream.java:482)
        - locked <0x000000008001d780> (a java.io.PrintStream)
        at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
        at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
        at sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:104)
        - locked <0x000000008001da58> (a java.io.OutputStreamWriter)
        at java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:185)
        at java.io.PrintStream.newLine(PrintStream.java:546)
        - eliminated <0x000000008001d780> (a java.io.PrintStream)
        at java.io.PrintStream.println(PrintStream.java:807)
        - locked <0x000000008001d780> (a java.io.PrintStream)
        at com.tanjie.java.jvm.JVM如何定位消耗CPU最高的线程$2.run(JVM如何定位消耗CPU最高的线程.java:22)

   Locked ownable synchronizers:
        - None

"Service Thread" #8 daemon prio=9 os_prio=0 tid=0x00007f799c119000 nid=0xb69 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"C1 CompilerThread1" #7 daemon prio=9 os_prio=0 tid=0x00007f799c0fc000 nid=0xb68 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"C2 CompilerThread0" #6 daemon prio=9 os_prio=0 tid=0x00007f799c0fa000 nid=0xb67 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"Signal Dispatcher" #5 daemon prio=9 os_prio=0 tid=0x00007f799c0f7800 nid=0xb66 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"Surrogate Locker Thread (Concurrent GC)" #4 daemon prio=9 os_prio=0 tid=0x00007f799c0f6000 nid=0xb65 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f799c0c3800 nid=0xb64 in Object.wait() [0x00007f7983d13000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x0000000080008ee0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
        - locked <0x0000000080008ee0> (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=0x00007f799c0be800 nid=0xb63 in Object.wait() [0x00007f7983d54000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x0000000080006b50> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:502)
        at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
        - locked <0x0000000080006b50> (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=0x00007f799c0b7000 nid=0xb62 runnable 

"Gang worker#0 (Parallel GC Threads)" os_prio=0 tid=0x00007f799c01a800 nid=0xb60 runnable 

"Concurrent Mark-Sweep GC Thread" os_prio=0 tid=0x00007f799c03d000 nid=0xb61 runnable 

"VM Periodic Task Thread" os_prio=0 tid=0x00007f799c124800 nid=0xb6a waiting on condition 

JNI global references: 9
    然后找到nid=0xb6e的线程堆栈,即可定位问题。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值