面試12-ConcurrentHashMap,HashMap,Hashtable的區(qū)別是什么?
2022-10-10 10:08 作者:架構(gòu)風(fēng)清揚-趣學(xué)旅程 | 我要投稿
1,首先,來看看其他幾個相關(guān)的類
Hashtable是線程安全的,但效率低
HashMap是線程不安全的,但效率高
Collections.synchronizedMap(),工具類提供了同步包裝器的方法,來返回具有線程安全的集合對象
性能依然有問題
為解決這樣的矛盾問題,所以JDK提供了并發(fā)包,來平衡這樣的問題(java.util.concurrent)
2,ConcurrentHashMap(重點)
兼顧了線程安全和效率的問題
分析:HashTable鎖了整段數(shù)據(jù)(用戶操作是不同的數(shù)據(jù)段,依然需要等待)
解決方案:把數(shù)據(jù)分段,執(zhí)行分段鎖(分離鎖),核心把鎖的范圍變小,這樣出現(xiàn)并發(fā)沖突的概率就變小
在保存的時候,計算所存儲的數(shù)據(jù)是屬于哪一段,只鎖當(dāng)前這一段
注意:分段鎖(分離鎖)是JDK1.8之前的一種的方案,JDK1.8之后做了優(yōu)化。
JDK1.7跟JDK1.8在ConcurrentHashMap的實現(xiàn)上存在以下區(qū)別:
1,數(shù)據(jù)結(jié)構(gòu)
JDK1.7采用鏈表的方式,而JDK1.8則采用鏈表+紅黑樹的方式
2,發(fā)生hash碰撞之后
JDK1.7發(fā)生碰撞之后,會采用鏈表的方式來解決
JDK1.8發(fā)生碰撞之后,默認采用鏈表,但當(dāng)鏈表的長度超過8,且數(shù)組容量超過64時,會轉(zhuǎn)換為紅黑樹存儲
3,保證并發(fā)安全
JDK1.7采用分段鎖的方式,而JDK1.8采用CAS和synchronized的組合模式
4,查詢復(fù)雜度
JDK1.7采用鏈表的方式,時間復(fù)雜度為O(n),而JDK1.8在采用紅黑樹的方式時,時間復(fù)雜度為O(log(n))
注意:
不過紅黑樹其實是一種兜底方案,因為當(dāng)鏈表數(shù)量達到8個的時候,其發(fā)生的概率是千萬分之幾,所以作者考慮到這種極端情況下,需要用紅黑樹的方式來優(yōu)化
標簽: