1、ConcurrentHashMap底層數(shù)據(jù)結(jié)構(gòu)是一個(gè)數(shù)組table
2念秧、table數(shù)組上掛著單向鏈表或紅黑樹
3松邪、new ConcurrentHashMap();如果沒有指定長(zhǎng)度的話,默認(rèn)是16继蜡,并且數(shù)組長(zhǎng)度必須是2的n次冪诗充,若自定義初始化的長(zhǎng)度不是2的n次冪苍蔬,那么在初始化數(shù)組時(shí),會(huì)吧數(shù)組長(zhǎng)度設(shè)置為大于自定義長(zhǎng)度的最近的2的n次冪蝴蜓。(如:自定義長(zhǎng)度為7碟绑,那么實(shí)際初始化數(shù)組后的長(zhǎng)度為8)
4、底層是使用synchronized作為同步鎖茎匠,并且鎖的粒度是數(shù)組的具體索引位(有些人稱之為分段鎖)格仲。
5、Node節(jié)點(diǎn)诵冒,hash>0凯肋,當(dāng)hash沖突時(shí),會(huì)形成一個(gè)單向鏈表掛在數(shù)組上造烁。
6否过、ForwardindNode,繼承至Node惭蟋,其hash=-1,表示當(dāng)前索引位的數(shù)據(jù)已經(jīng)被遷移到新數(shù)組上了
7药磺、ReservationNode告组,繼承至Node,其hash=-3癌佩,表示當(dāng)前索引位被占用了(compute方法)
8木缝、TreenBin便锨,繼承至Node,其hash=-2我碟,代表當(dāng)前索引下掛著一顆紅黑樹
9放案、lockState為ConcurrentHashMap底層自己實(shí)現(xiàn)的基于cas的讀寫鎖,鎖粒度是具體的某顆樹矫俺。當(dāng)向紅黑樹進(jìn)行增吱殉,刪操作時(shí),首先會(huì)先上sync同步鎖厘托,然后自平衡的時(shí)候會(huì)上lockState寫鎖友雳,當(dāng)讀紅黑樹的時(shí)候,會(huì)上lockState讀鎖铅匹,然后判斷此時(shí)是否有線程正持有寫鎖押赊,或是否有線程正在等待獲取寫鎖,若有包斑,則讀線程會(huì)直接去讀雙向鏈表流礁,而不是去讀紅黑樹。
10罗丰、TreeNode神帅,hash>0,為紅黑樹具體節(jié)點(diǎn)丸卷。TreeBin的root代表紅黑樹的根節(jié)點(diǎn)枕稀,first代表雙向鏈表的第一個(gè)節(jié)點(diǎn)
11、雙向鏈表:構(gòu)建紅黑樹時(shí)還維護(hù)了一個(gè)雙向鏈表谜嫉,其目的為:(1)當(dāng)并發(fā)寫讀同一顆紅黑樹的時(shí)候萎坷,讀線程判斷到有線程正持有寫鎖,那么會(huì)跑去讀取雙向鏈表沐兰,避免因?yàn)椴l(fā)寫讀導(dǎo)致讀線程等待或阻塞哆档。(2)當(dāng)擴(kuò)容的時(shí)候,會(huì)去遍歷雙向鏈表住闯,重新計(jì)算節(jié)點(diǎn)hash瓜浸,根據(jù)新的hash判斷放在新數(shù)組的高位還是地位
1、觸發(fā)擴(kuò)容的規(guī)則:
1)添加完元素后比原,若判斷到當(dāng)前容器元素個(gè)數(shù)達(dá)到了擴(kuò)容的閾值(數(shù)組長(zhǎng)度*0.75)插佛,則會(huì)觸發(fā)擴(kuò)容
2)添加完元素后,所在的單向鏈表長(zhǎng)度>=8量窘,則會(huì)轉(zhuǎn)為紅黑樹雇寇,不過在轉(zhuǎn)紅黑樹之前會(huì)判斷數(shù)組長(zhǎng)度是否小于64,若小于64則會(huì)觸發(fā)擴(kuò)容
2、table為擴(kuò)容前的數(shù)組锨侯,nextTable為擴(kuò)容中創(chuàng)建的新數(shù)組嫩海,遷移數(shù)據(jù)完畢后需要將nextTable賦值給table
3、擴(kuò)容后的數(shù)組是元素組長(zhǎng)度的2倍
4囚痴、ln叁怪,hn分別表示高位和低位的鏈表(高鏈,低鏈)深滚。即奕谭,擴(kuò)容時(shí),會(huì)用n&h==0來判斷元素應(yīng)該放在新數(shù)組的i位置還是i+n位置成箫。n:元素組長(zhǎng)度展箱;h:元素hash值;i:元素所在的原數(shù)組索引位蹬昌;混驰。這樣就會(huì)出現(xiàn)有些元素會(huì)被掛在低位,有些元素會(huì)被掛在高位皂贩,從而達(dá)到打散元素的目的栖榨。
5、紅黑樹擴(kuò)容時(shí)明刷,會(huì)遍歷雙向鏈表婴栽,并且計(jì)算n&h==0來判斷元素放在低位(lo)還是高位(ho),確定完元素的去處之后辈末,會(huì)判斷分別判斷兩個(gè)雙向鏈表(lo,ho)的長(zhǎng)度是否大于6愚争,若大于6則將還是以一顆紅黑樹的結(jié)構(gòu)掛在數(shù)組上,若<=6的話挤聘,則轉(zhuǎn)為單向鏈表轰枝,掛在數(shù)組上