背景
記得前段時間,同事說他們測試環境的伺服器cpu使用率一直處於100%,本地又沒有什麼介面呼叫,為什麼會這樣?cpu使用率居高不下,自然是有某些執行緒一直佔用著cpu資源,那又如何檢視佔用cpu較高的執行緒?
當然一個正常的程式設計師不會寫出上述程式碼,這裡只是為了讓一個執行緒佔用較高的cpu資源。
top命令
在linux環境下,可以通過top
命令檢視各個程式的cpu使用情況,預設按cpu使用率排序
1、上圖中可以看出pid為23344的java程式佔用了較多的cpu資源;
2、通過top -Hp 23344
可以檢視該程式下各個執行緒的cpu使用情況;
上圖中可以看出pid為25077的執行緒佔了較多的cpu資源,利用jstack命令可以繼續檢視該執行緒當前的堆疊狀態。
jstack命令
通過top命令定位到cpu佔用率較高的執行緒之後,繼續使用jstack pid
命令檢視當前java程式的堆疊狀態
jstack命令生成的thread dump資訊包含了JVM中所有存活的執行緒,為了分析指定執行緒,必須找出對應執行緒的呼叫棧,應該如何找?
在top命令中,已經獲取到了佔用cpu資源較高的執行緒pid,將該pid轉成16進位制的值,在thread dump中每個執行緒都有一個nid,找到對應的nid即可;隔段時間再執行一次stack命令獲取thread dump,區分兩份dump是否有差別,在nid=0x246c的執行緒呼叫棧中,發現該執行緒一直在執行JstackCase類第33行的calculate方法,得到這個資訊,就可以檢查對應的程式碼是否有問題。
通過thread dump分析執行緒狀態
除了上述的分析,大多數情況下會基於thead dump分析當前各個執行緒的執行情況,如是否存在死鎖、是否存在一個執行緒長時間持有鎖不放等等。
在dump中,執行緒一般存在如下幾種狀態:
1、RUNNABLE,執行緒處於執行中
2、BLOCKED,執行緒被阻塞
3、WAITING,執行緒正在等待
例項1:多執行緒競爭synchronized鎖
很明顯:執行緒1獲取到鎖,處於RUNNABLE狀態,執行緒2處於BLOCK狀態
1、locked
說明執行緒1對地址為0x000000076bf62208物件進行了加鎖;
2、waiting to lock
說明執行緒2在等待地址為0x000000076bf62208物件上的鎖;
3、waiting for monitor entry [0x000000001e21f000]
說明執行緒1是通過synchronized關鍵字進入了監視器的臨界區,並處於”Entry Set”佇列,等待monitor;
例項2:通過wait掛起執行緒
1 2 3 4 5 6 7 8 9 10 11 12 13 |
static class Task implements Runnable { @Override public void run() { synchronized (lock) { try { lock.wait(); //TimeUnit.SECONDS.sleep(100000); } catch (InterruptedException e) { e.printStackTrace(); } } } } |
dump結果
1、執行緒1和2都是先locked
,再waiting on
,之所以先鎖再等同一個物件,是因為wait方法需要先通過synchronized獲得該地址物件的monitor;
2、waiting on
說明執行緒執行了wait方法之後,釋放了monitor,進入到”Wait Set”佇列,等待其它執行緒執行地址為0x000000076bf62500物件的notify方法,並喚醒自己;
打賞支援我寫出更多好文章,謝謝!
打賞作者
打賞支援我寫出更多好文章,謝謝!