一、通過top命令定位佔用cpu高的進程
執行top命令得到以下結果(P按照進程負載排序):
通過上圖可以明顯看出進程PID2221 明顯存在問題,定位到了進程id。爲了更好的排查問題,下面詳細介紹top命令顯示的含義。
1)第一行是任務隊列信息
top - 14:06:34 up 537 days, 6 min, 6 users, load average: 0.41, 0.45, 0.43
任務隊列信息 | 含義 |
---|---|
14:06:34 | 當前時間 |
537 days | 系統運行時間 |
6 min | 用戶在線時間 |
6 users | 在線用戶數 |
load average: 0.41, 0.45, 0.43 | 系統負載,即任務隊列的平均長度。1分鐘前、5分鐘前、15分鐘前平均負載 |
2) 第二行爲進程的信息
進程信息 | 含義 |
---|---|
Tasks: 1 total | 進程總數 |
0 running | 正在運行的進程數 |
1 sleeping | 睡眠的進程數 |
0 stopped | 停止的進程數 |
0 zombie | 殭屍進程數 |
3)第三行爲cpu信息
cpu信息 | 含義 |
---|---|
6.1% us | 用戶空間佔用CPU百分比 |
1.5% sy | 內核空間佔用CPU百分比 |
0.0% ni | 用戶進程空間內改變過優先級的進程佔用CPU百分比 |
92.2% id | 空閒CPU百分比 |
0.0% wa | 等待輸入輸出的CPU時間百分比 |
0.0% hi | 硬件中斷 |
0.0% si | 軟件中斷 |
0.0%st | 實時 |
4)第四、五行爲內存信息,內容如下:
物理內存信息 | 含義 |
---|---|
Mem: 191272k total | 物理內存總量 |
173656k used | 使用的物理內存總量 |
17616k free | 空閒內存總量 |
22052k buffers | 用作內核緩存的內存量 |
交換區信息 | 含義 |
---|---|
Swap: 192772k total | 交換區總量 |
0k used | 使用的交換區總量 |
192772k free | 空閒交換區總量 |
123988k cached | 緩衝的交換區總量 |
二、通過top命令定位問題進程中每個線程佔用cpu情況
top -Hp 2221
查看進程PID 2221的每一個線程佔用CPU情況,如圖。
由上圖明顯可以發現,線程PID2244CPU佔用率最高,接下來定位該線程的代碼是否出現異常導致cpu佔用過高。
三、通過jstack 命令定位問題代碼
上一步發現線程PID2244佔用的CPU過高,就將這個PID轉換成16進制
printf “%x\n” 線程PID
printf “%x\n” 2244
PID 2244轉化成16進製爲8c4。使用如下命令命令定位問題代碼:
jstack pid |grep tid -A 30(pid:進程id,tid:線程id)
jstack 2221 | grep 8c4 -A 30
或者
jstack 2221| grep 8c4 -C5 --color
RUNNABLE 線程運行中或I/O等待
BLOCKED 線程在等待monitor鎖(synchronized關鍵字)
TIMED_WAITING 線程在等待喚醒,但設置了時限
WAITING 線程在無限等待喚醒
線程在等待的狀態。查看代碼
public String testCode(){
test();
return "success";
}
public void test(){
while(true){
for(int i=0;i<10;i++){
}
}
}
while循環無法結束,一直搶佔cpu,導致程序cpu使用過高,修改代碼即可。