您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關JDK7的HashMap和JDK8的ConcurrentHashMap造成CPU 100%的示例分析的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
大家可能都聽過JDK7中的HashMap在多線程環境下可能造成CPU 100%的現象,這個由于在擴容的時候put時產生了死鏈,由此會在get時造成了CPU 100%。這個問題在JDK8中的HashMap獲得了解決。其實JDK7中的HashMap在多線程環境下不止只有CPU 100%這一共怪異現象,它還可能造成插入的數據丟失。
對于HashMap多線程的問題,我們通常會這么反問:HashMap設計上就不是多線程安全的,何必要去在多線程環境下用呢?的確如此,我們不會傻到顯式的在多線程環境下調用,但是又可能在你所關注的視角范圍外是多線程的,其隱式地讓HashMap置于多線程環境下了,這個又難以一下子察覺到。再者,對于HashMap多線程的問題,我們很多時候推薦使用ConcurrentHashMap來代替HashMap應用于多線程的環境,很不巧的是ConcurrentHashMap也有可能會造成CPU 100%的異常現象。這個怪異現象存在于JDK8的ConcurrentHashMap中,在JDK9中已經得到修復,可以參見:https://bugs.openjdk.java.net/browse/JDK-8062841
什么情況下JDK8的ConcurrentHashMap會出現這個Bug呢?首先我們來運行一下這段代碼:
Map<String, String> map = new ConcurrentHashMap<>();
map.computeIfAbsent("AaAa",
key -> map.
computeIfAbsent("BBBB", key2 -> "value"));
你會驚奇的發現這個程序一直處于Running狀態,我們通過top -Hp [pid]命令查看到其中一個線程的CPU使用率接近100%,參考下圖:
可以看到pid為31417的東東,我們再通過jstack -l [pid]命令查看到對應的線程為:
注意將nid=0x7ab9的16進制轉為10進制就是31417。可以看到問題是發生在了computeIfAbsent方法中,我們將示例中的程序換成下面這段程序也會同樣出現CPU 100%的Bug:
map.computeIfAbsent("AaAa",
(String key) -> {
map.put("BBBB", "value");
return "value";
});
問題的關鍵在于遞歸使用了computeIfAbsent方法,筆者在stackoverflow上還搜索到了同類型的問題,下面的示例程序中調用fibonacci方法同樣也會造成CPU 100%.
static Map<Integer, Integer> concurrentMap = new ConcurrentHashMap<>();
public static void main(String[] args) {
System.out.println("Fibonacci result for 20 is" + fibonacci(20));
}
static int fibonacci(int i) {
if (i == 0)
return i;
if (i == 1)
return 1;
return concurrentMap.computeIfAbsent(i, (key) -> {
System.out.println("Value is " + key);
return fibonacci(i - 2) + fibonacci(i - 1);
});
}
感謝各位的閱讀!關于“JDK7的HashMap和JDK8的ConcurrentHashMap造成CPU 100%的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。