您的位置:首页 > 其它

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

2018-03-01 08:46 459 查看

一、需求分析

 
          经常听到朋友说他们线上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
4000
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的线程堆栈,即可定位问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: