并發(fā)包c(diǎn)oncurrent包下的ConcurrentHashmap
1.8以前是通過內(nèi)部分段的方式實(shí)現(xiàn)內(nèi)部分段,最多分16段,允許16個(gè)線程同時(shí)操作,通過細(xì)粒度鎖定的方式提高性能
1.8通過數(shù)組,鏈表,紅黑樹實(shí)現(xiàn)
內(nèi)部實(shí)現(xiàn)基本和hashMap一樣,只是在每個(gè)元素,即每條鏈表頭部加鎖,讓一個(gè)線程進(jìn)行操作.大量使用了voliate關(guān)鍵字和CAS算法
Node:保存key寂嘉,value及key的hash值的數(shù)據(jù)結(jié)構(gòu)奶浦。其中value和next都用volatile修飾,保證并發(fā)的可見性。
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
volatile V val;//volatile類型的
volatile Node<K,V> next;//volatile類型的
Node(int hash, K key, V val, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.val = val;
this.next = next;
}
//省略部分代碼
}
put流程
1、第一步根據(jù)給定的key的hash值找到其在table中的位置index。
2盆色、找到位置index后,存儲(chǔ)進(jìn)行就好了祟剔。
只是這里的存儲(chǔ)有三種情況罷了隔躲,第一種:table[index]中沒有任何其他元素,即此元素沒有發(fā)生碰撞物延,這種情況直接存儲(chǔ)就好了哈宣旱。第二種,table[i]存儲(chǔ)的是一個(gè)鏈表叛薯,如果鏈表不存在key則直接加入到鏈表尾部即可(這里與hashMap相反,hashMap將元素存放在鏈表頭部)浑吟,如果存在key則更新其對應(yīng)的value。第三種案训,table[i]存儲(chǔ)的是一個(gè)樹买置,則按照樹添加節(jié)點(diǎn)的方法添加就好。添加完成后,如果節(jié)點(diǎn)數(shù)>=8强霎,那么轉(zhuǎn)換鏈表結(jié)構(gòu)為紅黑樹結(jié)構(gòu).
get流程
1、根據(jù)key調(diào)用spread計(jì)算hash值蓉冈;并根據(jù)計(jì)算出來的hash值計(jì)算出該key在table出現(xiàn)的位置i.
2城舞、檢查table是否為空轩触;如果為空,返回null家夺,否則進(jìn)行3
3脱柱、檢查table[i]處桶位不為空;如果為空拉馋,則返回null榨为,否則進(jìn)行4
4、先檢查table[i]的頭結(jié)點(diǎn)的key是否滿足條件煌茴,是則返回頭結(jié)點(diǎn)的value随闺;否則分別根據(jù)樹、鏈表查詢蔓腐。