之前有朋友反饋說發(fā)的內(nèi)容希望有個梯度,逐步加深,前面發(fā)了幾篇關(guān)于jvm源碼分析的文章,可能我覺得我已經(jīng)把內(nèi)容寫得淺顯易懂了为黎,但是對于某些沒怎么接觸的同學(xué)來說還是比較難理解邮丰,這個我以后慢慢改進(jìn)吧行您,今天發(fā)篇輕松點(diǎn)的文章,可能大家在工作過程中也會可能碰到類似的問題剪廉,或許有經(jīng)驗(yàn)的同學(xué)看到這個題目就知道我要說什么了娃循,也有自己的定位方法。
話不多說了斗蒋,先來看代碼吧
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();
}
}
這個例子里新創(chuàng)建了11個線程捌斧,其中10個線程沒干什么事,主要是sleep泉沾,另外有一個線程在循環(huán)里一直跑著捞蚂,可以想象這個線程是這個進(jìn)程里最耗cpu的線程了,那怎么把這個線程給抓出來呢跷究?
首先我們可以通過top -Hp <pid>來看這個進(jìn)程里所有線程的cpu消耗情況姓迅,得到類似下面的數(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
拿到這個結(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
接著我們可以通過jstack <pid>的輸出來看各個線程棧:
$ 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的線程找出來了艘儒,是Businest Thread