ref:https://blog.csdn.net/xu768840497/article/details/79194701
http://www.cnblogs.com/leesf456/p/5453341.html
ConcurrentHashMap數據結構
ConcurrentHashMap相比HashMap而言,是多線程安全的,其底層數據與HashMap的數據結構相同,數據結構如下:
說明:ConcurrentHashMap的數據結構(數組+鏈表+紅黑樹),桶中的結構可能是鏈表,也可能是紅黑樹,紅黑樹是為了提高查找效率。
ConcurrentHashMap源碼分析
1、類的繼承關系
public class ConcurrentHashMap<K,V> extends AbstractMap<K,V> implements ConcurrentMap<K,V>, Serializable {}
說明:ConcurrentHashMap繼承了AbstractMap抽象類,該抽象類定義了一些基本操作,同時,也實現了ConcurrentMap接口,ConcurrentMap接口也定義了一系列操作,實現了Serializable接口表示ConcurrentHashMap可以被序列化。
2、類的內部類
ConcurrentHashMap包含了很多內部類,其中主要的內部類框架圖如下圖所示:
說明:可以看到,ConcurrentHashMap的內部類非常的龐大,第二個圖是在JDK1.8下增加的類,下面對其中主要的內部類進行分析和講解。
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的計數。
3 、類的屬性
public class ConcurrentHashMap<K,V> extends AbstractMap<K,V> implements ConcurrentMap<K,V>, Serializable { private static final long serialVersionUID = 7249069246763182397L; // 表的最大容量 private static final int MAXIMUM_CAPACITY = 1 << 30; // 默認表的大小 private static final int DEFAULT_CAPACITY = 16; // 最大數組大小 static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; // 默認並發數 private static final int DEFAULT_CONCURRENCY_LEVEL = 16; // 裝載因子 private static final float LOAD_FACTOR = 0.75f; // 轉化為紅黑樹的閾值 static final int TREEIFY_THRESHOLD = 8; // 由紅黑樹轉化為鏈表的閾值 static final int UNTREEIFY_THRESHOLD = 6; // 轉化為紅黑樹的表的最小容量 static final int MIN_TREEIFY_CAPACITY = 64; // 每次進行轉移的最小值 private static final int MIN_TRANSFER_STRIDE = 16; // 生成sizeCtl所使用的bit位數 private static int RESIZE_STAMP_BITS = 16; // 進行擴容所允許的最大線程數 private static final int MAX_RESIZERS = (1 << (32 - RESIZE_STAMP_BITS)) - 1; // 記錄sizeCtl中的大小所需要進行的偏移位數 private static final int RESIZE_STAMP_SHIFT = 32 - RESIZE_STAMP_BITS; // 一系列的標識 static final int MOVED = -1; // hash for forwarding nodes static final int TREEBIN = -2; // hash for roots of trees static final int RESERVED = -3; // hash for transient reservations static final int HASH_BITS = 0x7fffffff; // usable bits of normal node hash // /** Number of CPUS, to place bounds on some sizings */ // 獲取可用的CPU個數 static final int NCPU = Runtime.getRuntime().availableProcessors(); // /** For serialization compatibility. */ // 進行序列化的屬性 private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("segments", Segment[].class), new ObjectStreamField("segmentMask", Integer.TYPE), new ObjectStreamField("segmentShift", Integer.TYPE) }; // 表 transient volatile Node<K,V>[] table; // 下一個表 private transient volatile Node<K,V>[] nextTable; // /** * Base counter value, used mainly when there is no contention, * but also as a fallback during table initialization * races. Updated via CAS. */ // 基本計數 private transient volatile long baseCount; // /** * Table initialization and resizing control. When negative, the * table is being initialized or resized: -1 for initialization, * else -(1 + the number of active resizing threads). Otherwise, * when table is null, holds the initial table size to use upon * creation, or 0 for default. After initialization, holds the * next element count value upon which to resize the table. */ // 對表初始化和擴容控制 private transient volatile int sizeCtl; /** * The next table index (plus one) to split while resizing. */ // 擴容下另一個表的索引 private transient volatile int transferIndex; /** * Spinlock (locked via CAS) used when resizing and/or creating CounterCells. */ // 旋轉鎖 private transient volatile int cellsBusy; /** * Table of counter cells. When non-null, size is a power of 2. */ // counterCell表 private transient volatile CounterCell[] counterCells; // views // 視圖 private transient KeySetView<K,V> keySet; private transient ValuesView<K,V> values; private transient EntrySetView<K,V> entrySet; // Unsafe mechanics private static final sun.misc.Unsafe U; private static final long SIZECTL; private static final long TRANSFERINDEX; private static final long BASECOUNT; private static final long CELLSBUSY; private static final long CELLVALUE; private static final long ABASE; private static final int ASHIFT; static { try { U = sun.misc.Unsafe.getUnsafe(); Class<?> k = ConcurrentHashMap.class; SIZECTL = U.objectFieldOffset (k.getDeclaredField("sizeCtl")); TRANSFERINDEX = U.objectFieldOffset (k.getDeclaredField("transferIndex")); BASECOUNT = U.objectFieldOffset (k.getDeclaredField("baseCount")); CELLSBUSY = U.objectFieldOffset (k.getDeclaredField("cellsBusy")); Class<?> ck = CounterCell.class; CELLVALUE = U.objectFieldOffset (ck.getDeclaredField("value")); Class<?> ak = Node[].class; ABASE = U.arrayBaseOffset(ak); int scale = U.arrayIndexScale(ak); if ((scale & (scale - 1)) != 0) throw new Error("data type scale not a power of two"); ASHIFT = 31 - Integer.numberOfLeadingZeros(scale); } catch (Exception e) { throw new Error(e); } } }
說明:ConcurrentHashMap的屬性很多,其中不少屬性在HashMap中就已經介紹過,而對於ConcurrentHashMap而言,添加了Unsafe實例,主要用於反射獲取對象相應的字段。
4 、類的構造函數
1. ConcurrentHashMap()型構造函數
public ConcurrentHashMap() {
}
說明:該構造函數用於創建一個帶有默認初始容量 (16)、加載因子 (0.75) 和 concurrencyLevel (16) 的新的空映射。
2. ConcurrentHashMap(int)型構造函數
public ConcurrentHashMap(int initialCapacity) {
if (initialCapacity < 0) // 初始容量小於0,拋出異常 throw new IllegalArgumentException(); int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ? MAXIMUM_CAPACITY : tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1)); // 找到最接近該容量的2的冪次方數 // 初始化 this.sizeCtl = cap; }