一文學會Java死鎖和CPU 100% 問題的排查技巧

作一個積極的人html

編碼、改bug、提高本身java

我有一個樂園,面向編程,春暖花開git

工欲善其事,必先利其器github

 

 

00 本文簡介

做爲一名搞技術的程序猿或者是攻城獅,想必你應該是對下面這兩個問題有所瞭解,說不定你在實際的工做或者面試就有遇到過:面試

第一個問題:Java死鎖如何排查和解決?shell

第二個問題:服務器CPU佔用率高達到100%排查和解決?數據庫

第三個問題:有哪些工具可以快速查看線程使用狀況?編程

本文對這三個問題進行總結整理,經過實例演示講解,精彩乾貨,不容錯過啊!服務器

前戲就這麼多,高潮會不少,作好了,讓咱們直奔主題,發動小船,Let's go!工具

小船

01 Java死鎖排查和解決

要排查和解決死鎖,首先思考三個問題:

1. 什麼是死鎖?

2. 爲何會出現死鎖?

3. 怎麼排查代碼中出現了死鎖?

4. 如何避免寫出死鎖的代碼?

做爲技術人員(工程師),在出現問題的時候,可以儘快的去解決這個問題。可是在學習技術知識的時候,仍是腳踏實地,多問一些爲何,一個好的問題,可以讓本身思考,這方面的能力也必定要鍛鍊鍛鍊哦,這樣才能更好的理解和掌握知識,並探究/觸碰到更深刻的地方。

一、啥是死鎖?

死鎖是指兩個或兩個以上的進程在執行過程當中,因爲競爭資源或者因爲彼此通訊而形成的一種阻塞的現象,若無外力做用,它們都將沒法推動下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的進程稱爲死鎖進程。[百度百科:死鎖]

死鎖圖示

注:進程和線程均可以發生死鎖,只要知足死鎖的條件!

二、爲啥子會出現死鎖?

從上面的概念中咱們知道

(1)必須是兩個或者兩個以上進程(線程)

(2)必須有競爭資源

三、怎麼排查代碼中出現了死鎖?【重點來了】

首先整一個死鎖的代碼,看例子:

死鎖小demo

上面這段代碼執行後,就會出現死鎖,那麼排查的方法有以下:

第一個姿式:使用 jps + jstack

:在windons命令窗口,使用jps -l【不會使用jps請自行查詢資料】

jps -l 命令

:使用 jstack -l 12316 【不會使用jstack請自行查詢資料】

jstack

第二個姿式:使用jconsole

在window打開 JConsole,JConsole是一個圖形化的監控工具!

:在windons命令窗口 ,輸出 JConsole,以下圖:

這裏寫圖片描述

:選擇到線程的tab上,以下截圖。

這裏寫圖片描述

第三個姿式:使用Java Visual VM

在window打開 jvisualvm,jvisualvm是一個圖形化的監控工具!

:在windons命令窗口 ,輸出 jvisualvm

Java Visual VM

:依然是切換到線程這個TAB上,很明顯的就有提示!

死鎖檢測

四、如何避免死鎖?

上面說了死鎖出現的緣由以及經過三種方式來檢測和排查死鎖,下面更重要的東西來了,就是如何避免死鎖,若是可以讓寫出的代碼避免死鎖出現也就沒有上面這些排查的過程了。最好的是從源頭控制問題,而不是後期遇到問題在去填坑。

我看了阿里巴巴中最新的開發規約,裏面有對避免死鎖的說明,具體以下:


【強制】對多個資源、數據庫表、對象同時加鎖時,須要保持一致的加鎖順序,不然可能會 形成死鎖。 說明:線程一須要對錶 A、B、C 依次所有加鎖後才能夠進行更新操做,那麼線程二的加鎖順序也必須是 A、B、C,不然可能出現死鎖。


0二、Java CPU 100% 排查技巧

第一個姿式,步驟有點多,難度四星

平時多積累一點,這樣在遇到問題的時候就少句求人的話。若是在實際的開發中遇到CPU 100%問題,要怎麼排查呢?若是你沒有遇到過這個問題,請先本身思考10s,若是你遇到過,這個時候也正好能夠在回顧一遍。

、 使用top命令查看cpu佔用資源較高的PID

top命令

當前佔用cup100% 的PID爲3455。

、經過jps找到當前用戶下的java程序PID

執行jps -l可以打印出全部的應用的PID,找到有一個PID和這個cpu使用100%同樣的ID!!!就知道是哪個服務了。知道了對應的服務,在接着後續的分析步驟。

、 使用 pidstat -p < PID > 1 3 -u -t

-p:指定進程號
-u:默認的參數,顯示各個進程的cpu使用統計
-t:顯示選擇任務的線程的統計信息外的額外信息

這裏寫圖片描述這裏寫圖片描述

、找到cpu佔用較高的線程TID ,經過上圖發現是 3467的TID佔用cup較大

、 由於jstack命令輸出文件記錄的線程ID是16進制。所以咱們先將TID轉換爲十六進制的表示方式,轉換方式能夠參考下圖。

3467轉爲十六進制 d8d,注意是小寫!! 記錄下來,後面會使用。

巧轉進制、經過jstack [-l] PID輸出當前進程的線程信息

jstack PID  /temp/test.log

、查找 TID對應的線程(輸出的線程id爲十六進制),找到對應的代碼,使用命令查找哦,不要肉眼比對,具體命令請思考,給你表現機會。

查找

找到以後具體分析這個線程在幹什麼,爲何會佔用這麼多的 CUP資源。

PS:線程的幾種狀態以下說明:

NEW,未啓動的。不會出如今Dump中。
RUNNABLE,在虛擬機內執行的。
BLOCKED,受阻塞並等待監視器鎖。
WATING,無限期等待另外一個線程執行特定操做。
TIMED_WATING,有時限的等待另外一個線程的特定操做。
TERMINATED,已退出的。

第二個姿式,待開發[奸笑臉]

此處省略……,好多字。

03 推薦兩個高效排查問題工具

 :show-busy-java-threads

在這裏插入圖片描述

官網地址:show-busy-java-threads: https://github.com/oldratlee/useful-scripts/blob/master/docs/java.md#-show-busy-java-threads

簡單安裝和使用過程:

  1. 下載 show-busy-java-threads
  2. 上傳服務器,而後進行解壓
  3. 而後執行對應的命令

這裏寫圖片描述

:阿里開源的問題定位神器 arthas 來定位問題。

官網地址:arthas :https://alibaba.github.io/arthas/index.html

這個裏面有不少命令,如thread 支持一鍵展現當前最忙的前N個線程並打印堆棧,最簡單的 thread -n 10 便可將最忙碌的十個線程快照打印出來,真正高效。

在這裏插入圖片描述

定位神器 arthas 安裝過程就作介紹了,若是你尚未用過這個工具,我建議必定去用一下,說不定你會愛上它!

04 總結

本文內容比較多,基本上是手把手的教程了,但願可以對你有所幫助,也建議沒有遇到相似問題的夥伴,看完以後必定要親自去實踐一下操做過程,若是沒有環境能夠自行想辦法搞一個測試例子。仍是老話:不要眼高手低,看了和作了本質上兩個概念,最終收穫的也必定不一樣。

05 彩蛋-另外一個姿式

也能夠經過使用jstack找到系統的代碼性能問題

一、在進行壓力測試的時候,使用jps找到應用的PID

二、而後使用jstack輸出出壓力測試時候應用的dump信息

三、分析輸出的日誌文件中那個方法block線程佔用最多,這裏多是性能有問題,找到對應的代碼分析


謝謝你的閱讀,若是您以爲這篇博文對你有幫助,請點贊或者喜歡,讓更多的人看到!祝你天天開心愉快!


 

無論作什麼,只要堅持下去就會看到不同!在路上,不卑不亢!

 

願你我在人生的路上能都變成最好的本身,可以成爲一個獨擋一面的人

© 天天都在變得更好的阿飛雲

原文出處:https://www.cnblogs.com/aflyun/p/11141369.html

相關文章
相關標籤/搜索