一般在进程中都是存在多个线程,然而有可能存在特别耗费CPU的线程,但是如何去定位它们呢,下面通过一段代码来看看
package demo;public class TestThreadCpu { public static void main(String[] args) { for(int i = 0; i < 10; i++){ new Thread(){ @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }.start(); } Thread t = new Thread(){ @Override public void run() { int i = 0; while(true){ i=(i++)/100; } } }; t.setName("Busiest Thread"); t.start(); }}
这个例子里新建了 11个线程,其中10个线程没干啥,主要就是 sleep 另外一个线程循环的跑着,可以看出,这个单独的线程是当前进程里面最耗 CPU 的线程了。
下面我们怎么来将这个单独的线程抓出来呢?
首先 我们通过 top -Hp <pid> 来看这个进程里所有的线程CPU消耗情况,得到如下数据
$ top -Hp 18207top - 19:11:43 up 573 days, 2:43, 2 users, load average: 3.03, 3.03, 3.02Tasks: 44 total, 1 running, 43 sleeping, 0 stopped, 0 zombieCpu(s): 18.8%us, 0.0%sy, 0.0%ni, 81.1%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%stMem: 99191752k total, 98683576k used, 508176k free, 128248k buffersSwap: 1999864k total, 191064k used, 1808800k free, 17413760k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND18250 admin 20 0 26.1g 28m 10m R 99.9 0.0 0:19.50 java TestThreadCpu 18207 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java TestThreadCpu 18208 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.09 java TestThreadCpu 18209 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java TestThreadCpu 18210 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java TestThreadCpu 18211 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java TestThreadCpu 18212 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java TestThreadCpu 18213 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java TestThreadCpu 18214 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java TestThreadCpu 18215 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java TestThreadCpu 18216 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java TestThreadCpu 18217 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java TestThreadCpu 18218 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java TestThreadCpu 18219 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java TestThreadCpu 18220 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java TestThreadCpu 18221 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java TestThreadCpu 18222 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java TestThreadCpu 18223 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java TestThreadCpu 18224 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java TestThreadCpu 18225 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java TestThreadCpu 18226 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java TestThreadCpu 18227 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java TestThreadCpu 拿到这个结果之后,我们可以看到cpu最高的线程是pid为18250的线程,占了99.8%: PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND18250 admin 20 0 26.1g 28m 10m R 99.9 0.0 0:19.50 java TestThreadCpu
接下来我们可以通过 jstack <pid> 的输出来哥哥线程栈:
$ jstack 182072016-03-30 19:12:23Full thread dump OpenJDK 64-Bit Server VM (25.66-b60 mixed mode):"Attach Listener" #30 daemon prio=9 os_prio=0 tid=0x00007fb90be13000 nid=0x47d7 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE"DestroyJavaVM" #29 prio=5 os_prio=0 tid=0x00007fb96245b800 nid=0x4720 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE"Busiest Thread" #28 prio=5 os_prio=0 tid=0x00007fb91498d000 nid=0x474a runnable [0x00007fb9065fe000] java.lang.Thread.State: RUNNABLE at Test$2.run(Test.java:18)"Thread-9" #27 prio=5 os_prio=0 tid=0x00007fb91498c800 nid=0x4749 waiting on condition [0x00007fb906bfe000] java.lang.Thread.State: TIMED_WAITING (sleeping) at java.lang.Thread.sleep(Native Method) at Test$1.run(Test.java:9)"Thread-8" #26 prio=5 os_prio=0 tid=0x00007fb91498b800 nid=0x4748 waiting on condition [0x00007fb906ffe000] java.lang.Thread.State: TIMED_WAITING (sleeping) at java.lang.Thread.sleep(Native Method) at Test$1.run(Test.java:9)"Thread-7" #25 prio=5 os_prio=0 tid=0x00007fb91498b000 nid=0x4747 waiting on condition [0x00007fb9073fe000] java.lang.Thread.State: TIMED_WAITING (sleeping) at java.lang.Thread.sleep(Native Method) at Test$1.run(Test.java:9)"Thread-6" #24 prio=5 os_prio=0 tid=0x00007fb91498a000 nid=0x4746 waiting on condition [0x00007fb9077fe000] java.lang.Thread.State: TIMED_WAITING (sleeping) at java.lang.Thread.sleep(Native Method) at Test$1.run(Test.java:9)...
上面我们注意到 nid 的值 就是我们的线程ID,它是16进制 ,我们最消耗 CPU 的最高的线程 18250,转化成 16进制 0x47A 然后从上面的线程栈里面找到 nid=0x47A 的线程,其栈为
"Busiest Thread" #28 prio=5 os_prio=0 tid=0x00007fb91498d000 nid=0x474a runnable [0x00007fb9065fe000] java.lang.Thread.State: RUNNABLE at Test$2.run(Test.java:18)
即将最耗CPU的线程找出来了,就是 Businest Thread