ConcurrentHashMap 的工作原理及代碼實現:
相比於1.7版本,它做了兩個改進
1、取消了segment分段設計,直接使用Node數組來保存數據,並且采用Node數組元素作為鎖來實現每一行數據進行加鎖來進一步減少並發沖突的概率
2、將原本數組+單向鏈表的數據結構變更為了數組+單向鏈表+紅黑樹的結構。為什么要引入紅黑樹呢?在正常情況下,key hash之后如果能夠很均勻的分散在數組中,那么table數組中的每個隊列的長度主要為0或者1.但是實際情況下,還是會存在一些隊列長度過長的情況。如果還采用單向列表方式,那么查詢某個節點的時間復雜度就變為O(n); 因此對於隊列長度超過8的列表,JDK1.8采用了紅黑樹的結構,那么查詢的時間復雜度就會降低到O(logN),可以提升查找的性能;
JDK1.8中,Segment類只有在序列化和反序列化時才會被用到;
拋棄了原有的 Segment 分段鎖,而采用了 CAS + synchronized
來保證並發安全性。
transient volatile Node<K,V>[] table;
static class Node<K,V> implements Map.Entry<K,V> { final int hash; final K key; volatile V val; volatile Node<K,V> next; Node(int hash, K key, V val, Node<K,V> next) { this.hash = hash; this.key = key; this.val = val; this.next = next; } }
1. Node類
Node類主要用於存儲具體鍵值對,其子類有ForwardingNode、ReservationNode、TreeNode和TreeBin四個子類。四個子類具體的代碼在之后的具體例子中進行分析講解。
2. Traverser類
Traverser類主要用於遍歷操作,其子類有BaseIterator、KeySpliterator、ValueSpliterator、EntrySpliterator四個類,BaseIterator用於遍歷操作。KeySplitertor、ValueSpliterator、EntrySpliterator則用於鍵、值、鍵值對的划分。
3. CollectionView類
CollectionView抽象類主要定義了視圖操作,其子類KeySetView、ValueSetView、EntrySetView分別表示鍵視圖、值視圖、鍵值對視圖。對視圖均可以進行操作。
4. Segment類
Segment類在JDK1.8中與之前的版本的JDK作用存在很大的差別,JDK1.8下,其在普通的ConcurrentHashMap操作中已經沒有失效,其在序列化與反序列化的時候會發揮作用。
5. CounterCell
CounterCell類主要用於對baseCount的計數。
如何統計所有的元素個數:
transient volatile CounterCell[] counterCells; 可方便的計算hashmap中所有元素的個數,性能大大優於jdk1.7中的size()方法