如何定位消耗CPU最多的線程
之前有朋友反饋說(shuō)發(fā)的內(nèi)容希望有個(gè)梯度,逐步加深,前面發(fā)了幾篇關(guān)于jvm源碼分析的文章,可能我覺(jué)得我已經(jīng)把內(nèi)容寫(xiě)得淺顯易懂了,但是對(duì)于某些沒(méi)怎么接觸的同學(xué)來(lái)說(shuō)還是比較難理解,這個(gè)我以后慢慢改進(jìn)吧,今天發(fā)篇輕松點(diǎn)的文章,可能大家在工作過(guò)程中也會(huì)可能碰到類(lèi)似的問(wèn)題,或許有經(jīng)驗(yàn)的同學(xué)看到這個(gè)題目就知道我要說(shuō)什么了,也有自己的定位方法。
話不多說(shuō)了,先來(lái)看代碼吧
- public class Test{
- 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("Busiest Thread");
- t.start();
- }
- }
這個(gè)例子里新創(chuàng)建了11個(gè)線程,其中10個(gè)線程沒(méi)干什么事,主要是sleep,另外有一個(gè)線程在循環(huán)里一直跑著,可以想象這個(gè)線程是這個(gè)進(jìn)程里最耗cpu的線程了,那怎么把這個(gè)線程給抓出來(lái)呢?
首先我們可以通過(guò)top -Hp <pid>來(lái)看這個(gè)進(jìn)程里所有線程的cpu消耗情況,得到類(lèi)似下面的數(shù)據(jù)
- $ top -Hp 18207
- top - 19:11:43 up 573 days, 2:43, 2 users, load average: 3.03, 3.03, 3.02
- Tasks: 44 total, 1 running, 43 sleeping, 0 stopped, 0 zombie
- Cpu(s): 18.8%us, 0.0%sy, 0.0%ni, 81.1%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
- Mem: 99191752k total, 98683576k used, 508176k free, 128248k buffers
- Swap: 1999864k total, 191064k used, 1808800k free, 17413760k cached
- PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
- 18250 admin 20 0 26.1g 28m 10m R 99.9 0.0 0:19.50 java Test
- 18207 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java Test
- 18208 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.09 java Test
- 18209 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java Test
- 18210 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java Test
- 18211 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java Test
- 18212 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java Test
- 18213 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java Test
- 18214 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java Test
- 18215 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java Test
- 18216 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java Test
- 18217 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java Test
- 18218 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java Test
- 18219 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java Test
- 18220 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java Test
- 18221 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java Test
- 18222 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java Test
- 18223 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java Test
- 18224 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java Test
- 18225 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java Test
- 18226 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java Test
- 18227 admin 20 0 26.1g 28m 10m S 0.0 0.0 0:00.00 java Test
拿到這個(gè)結(jié)果之后,我們可以看到cpu***的線程是pid為18250的線程,占了99.8%:
- PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
- 18250 admin 20 0 26.1g 28m 10m R 99.9 0.0 0:19.50 java Test
接著我們可以通過(guò)jstack <pid>的輸出來(lái)看各個(gè)線程棧:
- $ jstack 18207
- 2016-03-30 19:12:23
- Full 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的值其實(shí)就是線程ID,它是十六進(jìn)制的,我們將消耗cpu***的線程18250,轉(zhuǎn)成十六進(jìn)制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的線程找出來(lái)了,是Businest Thread
【本文是51CTO專欄作者李嘉鵬的原創(chuàng)文章,轉(zhuǎn)載請(qǐng)通過(guò)微信公眾號(hào)(你假笨,id:lovestblog)聯(lián)系作者本人獲取授權(quán)】