你們可能都聽過JDK7中的HashMap在多線程環境下可能形成CPU 100%的現象,這個因爲在擴容的時候put時產生了死鏈,由此會在get時形成了CPU 100%。這個問題在JDK8中的HashMap得到了解決。其實JDK7中的HashMap在多線程環境下不止只有CPU 100%這一共怪異現象,它還可能形成插入的數據丟失,有興趣的讀者能夠自行了解下。java
對於HashMap多線程的問題,咱們一般會這麼反問:HashMap設計上就不是多線程安全的,何須要去在多線程環境下用呢?的確如此,咱們不會傻到顯式的在多線程環境下調用,可是又可能在你所關注的視角範圍外是多線程的,其隱式地讓HashMap置於多線程環境下了,這個又難以一會兒察覺到。再者,對於HashMap多線程的問題,咱們不少時候推薦使用ConcurrentHashMap來代替HashMap應用於多線程的環境,很不巧的是ConcurrentHashMap也有可能會形成CPU 100%的異常現象。這個怪異現象存在於JDK8的ConcurrentHashMap中,在JDK9中已經獲得修復,能夠參見:安全
https://bugs.openjdk.java.net/browse/JDK-8062841多線程
什麼狀況下JDK8的ConcurrentHashMap會出現這個Bug呢?首先咱們來運行一下這段代碼:架構
你會驚奇的發現這個程序一直處於Running狀態,咱們經過top -Hp [pid]命令查看到其中一個線程的CPU使用率接近100%,參考下圖:學習
能夠看到pid爲31417的東東,咱們再經過jstack -l [pid]命令查看到對應的線程爲:.net
注意將nid=0x7ab9的16進制轉爲10進制就是31417。能夠看到問題是發生在了computeIfAbsent方法中,咱們將示例中的程序換成下面這段程序也會一樣出現CPU 100%的Bug:線程
問題的關鍵在於遞歸使用了computeIfAbsent方法,筆者在stackoverflow上還搜索到了同類型的問題,下面的示例程序中調用fibonacci方法一樣也會形成CPU 100%.設計
至於爲何會發生這個BUG,答案就在ConcurrentHashMap中的computeIfAbsent方法中,本身去撈吧,嘿嘿。或者等之後的文章。怎麼規避這個問題呢?只要不在遞歸中使用computeIfAbsent方法就好啦,或者降級用可愛的分段鎖,或者升級JDK9。3d
歡迎工做一到八年的Java工程師朋友們加入Java高級交流:787707172blog
本羣提供免費的學習指導 架構資料 以及免費的解答
不懂得問題均可以在本羣提出來 以後還會有直播平臺和講師直接交流噢