2、table數組上掛著單向鏈表或紅黑樹
3、new ConcurrentHashMap();如果沒有指定長度的話,默認是16,並且數組長度必須是2的n次冪,若自定義初始化的長度不是2的n次冪,那麽在初始化數組時,會吧數組長度設置為大於自定義長度的最近的2的n次冪。(如:自定義長度為7,那麽實際初始化數組後的長度為8)
4、底層是使用synchronized作為同步鎖,並且鎖的粒度是數組的具體索引位(有些人稱之為分段鎖)。
5、Node節點,hash>0,當hash沖突時,會形成壹個單向鏈表掛在數組上。
6、ForwardindNode,繼承至Node,其hash=-1,表示當前索引位的數據已經被遷移到新數組上了
7、ReservationNode,繼承至Node,其hash=-3,表示當前索引位被占用了(compute方法)
8、TreenBin,繼承至Node,其hash=-2,代表當前索引下掛著壹顆紅黑樹
9、lockState為ConcurrentHashMap底層自己實現的基於cas的讀寫鎖,鎖粒度是具體的某顆樹。當向紅黑樹進行增,刪操作時,首先會先上sync同步鎖,然後自平衡的時候會上lockState寫鎖,當讀紅黑樹的時候,會上lockState讀鎖,然後判斷此時是否有線程正持有寫鎖,或是否有線程正在等待獲取寫鎖,若有,則讀線程會直接去讀雙向鏈表,而不是去讀紅黑樹。
10、TreeNode,hash>0,為紅黑樹具體節點。TreeBin的root代表紅黑樹的根節點,first代表雙向鏈表的第壹個節點
11、雙向鏈表:構建紅黑樹時還維護了壹個雙向鏈表,其目的為:(1)當並發寫讀同壹顆紅黑樹的時候,讀線程判斷到有線程正持有寫鎖,那麽會跑去讀取雙向鏈表,避免因為並發寫讀導致讀線程等待或阻塞。(2)當擴容的時候,會去遍歷雙向鏈表,重新計算節點hash,根據新的hash判斷放在新數組的高位還是地位
1、觸發擴容的規則:
1)添加完元素後,若判斷到當前容器元素個數達到了擴容的閾值(數組長度*0.75),則會觸發擴容
2)添加完元素後,所在的單向鏈表長度>=8,則會轉為紅黑樹,不過在轉紅黑樹之前會判斷數組長度是否小於64,若小於64則會觸發擴容
2、table為擴容前的數組,nextTable為擴容中創建的新數組,遷移數據完畢後需要將nextTable賦值給table
3、擴容後的數組是元素組長度的2倍
4、ln,hn分別表示高位和低位的鏈表(高鏈,低鏈)。即,擴容時,會用n&h==0來判斷元素應該放在新數組的i位置還是i+n位置。n:元素組長度;h:元素hash值;i:元素所在的原數組索引位;。這樣就會出現有些元素會被掛在低位,有些元素會被掛在高位,從而達到打散元素的目的。
5、紅黑樹擴容時,會遍歷雙向鏈表,並且計算n&h==0來判斷元素放在低位(lo)還是高位(ho),確定完元素的去處之後,會判斷分別判斷兩個雙向鏈表(lo,ho)的長度是否大於6,若大於6則將還是以壹顆紅黑樹的結構掛在數組上,若<=6的話,則轉為單向鏈表,掛在數組上