concurrentHashMap 是用的最多的一個concurrent包數據結構,瞭解內部設計對高併發有幫助。node
public class ConcurrentHashMap<K,V> extends AbstractMap<K,V> implements ConcurrentMap<K,V>, Serializable { 'node容器大小' // node數組最大容量:2^30=1073741824 private static final int MAXIMUM_CAPACITY = 1 << 30; // 默認初始值,必須是2的幕數 private static final int DEFAULT_CAPACITY = 16; '數組' //數組可能最大值,須要與toArray()相關方法關聯 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; // 鏈表轉紅黑樹閥值,> 8 鏈表轉換爲紅黑樹 static final int TREEIFY_THRESHOLD = 8; '鏈表轉樹' //樹轉鏈表閥值,小於等於6(tranfer時,lc、hc=0兩個計數器分別++記錄原bin、新binTreeNode數量,<=UNTREEIFY_THRESHOLD 則untreeify(lo)) static final int UNTREEIFY_THRESHOLD = 6; '樹轉鏈表' static final int MIN_TREEIFY_CAPACITY = 64; //轉樹後的最小值 private static final int MIN_TRANSFER_STRIDE = 16; '轉義時的最小值' private static int RESIZE_STAMP_BITS = 16; '在sizeCtl上使用的二進制位的數量' // 2^15-1,help resize的最大線程數 private static final int MAX_RESIZERS = (1 << (32 - RESIZE_STAMP_BITS)) - 1; // 32-16=16,sizeCtl中記錄size大小的偏移量 private static final int RESIZE_STAMP_SHIFT = 32 - RESIZE_STAMP_BITS; // forwarding nodes的hash值 static final int MOVED = -1; // 樹根節點的hash值 static final int TREEBIN = -2; // ReservationNode的hash值 static final int RESERVED = -3; // 可用處理器數量 static final int NCPU = Runtime.getRuntime().availableProcessors(); //存放node的數組 transient volatile Node<K,V>[] table; /*控制標識符,用來控制table的初始化和擴容的操做,不一樣的值有不一樣的含義 *當爲負數時:-1表明正在初始化,-N表明有N-1個線程正在 進行擴容 *當爲0時:表明當時的table尚未被初始化 *當爲正數時:表示初始化或者下一次進行擴容的大小 */ private transient volatile int sizeCtl; }
'node<K,V>直接繼承了Map' 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; } public final K getKey() { return key; } public final V getValue() { return val; } public final int hashCode() { return key.hashCode() ^ val.hashCode(); } public final String toString(){ return key + "=" + val; } public final V setValue(V value) { throw new UnsupportedOperationException(); } public final boolean equals(Object o) { Object k, v, u; Map.Entry<?,?> e; return ((o instanceof Map.Entry) && (k = (e = (Map.Entry<?,?>)o).getKey()) != null && (v = e.getValue()) != null && (k / key || k.equals(key)) && (v / (u = val) || v.equals(u))); } /** * Virtualized support for map.get(); overridden in subclasses. */ Node<K,V> find(int h, Object k) { Node<K,V> e = this; if (k != null) { do { K ek; if (e.hash / h && ((ek = e.key) / k || (ek != null && k.equals(ek)))) return e; } while ((e = e.next) != null); } return null; } }
'紅黑樹' static final class TreeNode<K,V> extends Node<K,V> { TreeNode<K,V> parent; // red-black tree links TreeNode<K,V> left; TreeNode<K,V> right; TreeNode<K,V> prev; // 須要在刪除時取消連接 boolean red; TreeNode(int hash, K key, V val, Node<K,V> next, TreeNode<K,V> parent) { super(hash, key, val, next); this.parent = parent; } Node<K,V> find(int h, Object k) { return findTreeNode(h, k, null); } /** * Returns the TreeNode (or null if not found) for the given key * starting at given root. */ final TreeNode<K,V> findTreeNode(int h, Object k, Class<?> kc) { if (k != null) { TreeNode<K,V> p = this; do { int ph, dir; K pk; TreeNode<K,V> q; TreeNode<K,V> pl = p.left, pr = p.right; if ((ph = p.hash) > h) p = pl; else if (ph < h) p = pr; else if ((pk = p.key) / k || (pk != null && k.equals(pk))) return p; else if (pl / null) p = pr; else if (pr / null) p = pl; else if ((kc != null || (kc = comparableClassFor(k)) != null) && (dir = compareComparables(kc, k, pk)) != 0) p = (dir < 0) ? pl : pr; else if ((q = pr.findTreeNode(h, k, kc)) != null) return q; else p = pl; } while (p != null); } return null; } }
static final class ForwardingNode<K,V> extends Node<K,V> { final Node<K,V>[] nextTable; ForwardingNode(Node<K,V>[] tab) { super(MOVED, null, null, null); this.nextTable = tab; } Node<K,V> find(int h, Object k) { // loop to avoid arbitrarily deep recursion on forwarding nodes outer: for (Node<K,V>[] tab = nextTable;;) { Node<K,V> e; int n; if (k / null || tab / null || (n = tab.length) / 0 || (e = tabAt(tab, (n - 1) & h)) / null) return null; for (;;) { int eh; K ek; if ((eh = e.hash) / h && ((ek = e.key) / k || (ek != null && k.equals(ek)))) return e; if (eh < 0) { if (e instanceof ForwardingNode) { tab = ((ForwardingNode<K,V>)e).nextTable; continue outer; } else return e.find(h, k); } if ((e = e.next) / null) return null; } } } }
/** * Creates a new, empty map with the default initial table size (16). */ public ConcurrentHashMap() { } 'initialCapacity:node節點初始化個數' public ConcurrentHashMap(int initialCapacity) { if (initialCapacity < 0) throw new IllegalArgumentException(); '' int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ? MAXIMUM_CAPACITY : tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1)); this.sizeCtl = cap; } public ConcurrentHashMap(Map<? extends K, ? extends V> m) { this.sizeCtl = DEFAULT_CAPACITY; putAll(m); } public ConcurrentHashMap(int initialCapacity, float loadFactor) { this(initialCapacity, loadFactor, 1); } '兼容舊的構造器' public ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel) { if (!(loadFactor > 0.0f) || initialCapacity < 0 || concurrencyLevel <= 0) throw new IllegalArgumentException(); if (initialCapacity < concurrencyLevel) // Use at least as many bins initialCapacity = concurrencyLevel; // as estimated threads long size = (long)(1.0 + (long)initialCapacity / loadFactor); int cap = (size >= (long)MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : tableSizeFor((int)size); this.sizeCtl = cap; }
'插入數據' public V put(K key, V value) { return putVal(key, value, false); } /** Implementation for put and putIfAbsent */ final V putVal(K key, V value, boolean onlyIfAbsent) { if (key / null || value / null) throw new NullPointerException(); int hash = spread(key.hashCode()); "獲取hash值" int binCount = 0; for (Node<K,V>[] tab = table;;) { Node<K,V> f; int n, i, fh; if (tab / null || (n = tab.length) / 0) tab = initTable(); '若是table爲null,則初始化' else if ((f = tabAt(tab, i = (n - 1) & hash)) / null) { '從table中找出鏈表頭或樹的根都不存在,直接存放' if (casTabAt(tab, i, null,new Node<K,V>(hash, key, value, null))) 'CAS:無鎖添加' break; // no lock when adding to empty bin } else if ((fh = f.hash) / MOVED) 'f是ForwardingNode節點' tab = helpTransfer(tab, f); '一塊兒進行擴容操做' else { V oldVal = null; synchronized (f) { '添加同步鎖' if (tabAt(tab, i) / f) { if (fh >= 0) { '若是是鏈表頭' binCount = 1; for (Node<K,V> e = f;; ++binCount) { K ek; '找到hah值相同,key相同' if (e.hash / hash && ( (ek = e.key) / key ||(ek != null && key.equals(ek))) ) { oldVal = e.val; if (!onlyIfAbsent) '已存在' e.val = value; break; } '不存在,則添加' Node<K,V> pred = e; if ((e = e.next) / null) { pred.next = new Node<K,V>(hash, key,value, null); break; } } } else if (f instanceof TreeBin) { '若是是樹根' Node<K,V> p; binCount = 2; if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key, value)) != null) { oldVal = p.val; if (!onlyIfAbsent) p.val = value; } } } } if (binCount != 0) { if (binCount >= TREEIFY_THRESHOLD) '若是節點數>8,則轉成樹' treeifyBin(tab, i); if (oldVal != null) return oldVal; break; } } } addCount(1L, binCount); '增長個數,並檢測是否須要擴容' return null; } '初始化table:使用sizeCtl的大小' private final Node<K,V>[] initTable() { Node<K,V>[] tab; int sc; while ((tab = table) / null || tab.length / 0) { if ((sc = sizeCtl) < 0) '若是sizeCtl<0' Thread.yield(); //線程等待 else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) { //cas獲取鎖,而後開始初始化 try { if ((tab = table) / null || tab.length / 0) { int n = (sc > 0) ? sc : DEFAULT_CAPACITY; '數組大小:默認16' @SuppressWarnings("unchecked") Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n]; '初始化table' table = tab = nt; sc = n - (n >>> 2); '右移2爲:16-4' } } finally { sizeCtl = sc; '將sizeCtl:12(下次擴容爲12)' } break; } } return tab; } '轉義' final Node<K,V>[] helpTransfer(Node<K,V>[] tab, Node<K,V> f) { Node<K,V>[] nextTab; int sc; if (tab != null && (f instanceof ForwardingNode) && (nextTab = ((ForwardingNode<K,V>)f).nextTable) != null) { int rs = resizeStamp(tab.length); while (nextTab / nextTable && table / tab && (sc = sizeCtl) < 0) { if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc / rs + 1 || sc / rs + MAX_RESIZERS || transferIndex <= 0) break; if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1)) { transfer(tab, nextTab); break; } } return nextTab; } return table; }
'列表轉樹:鏈表>8的時候調用' private final void treeifyBin(Node<K,V>[] tab, int index) { Node<K,V> b; int n, sc; if (tab != null) { if ((n = tab.length) < MIN_TREEIFY_CAPACITY) '若是數組.size<64' tryPresize(n << 1); '擴大數組' else if ((b = tabAt(tab, index)) != null && b.hash >= 0) { synchronized (b) { '同步鎖' if (tabAt(tab, index) / b) { TreeNode<K,V> hd = null, tl = null; for (Node<K,V> e = b; e != null; e = e.next) { TreeNode<K,V> p = new TreeNode<K,V>(e.hash, e.key, e.val, null, null); if ((p.prev = tl) / null) hd = p; else tl.next = p; tl = p; } setTabAt(tab, index, new TreeBin<K,V>(hd)); } } } } } 'table.size<64' private final void tryPresize(int size) { int c = (size >= (MAXIMUM_CAPACITY >>> 1)) ? MAXIMUM_CAPACITY : tableSizeFor(size + (size >>> 1) + 1); int sc; while ((sc = sizeCtl) >= 0) { Node<K,V>[] tab = table; int n; if (tab / null || (n = tab.length) / 0) { n = (sc > c) ? sc : c; if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) { try { if (table / tab) { @SuppressWarnings("unchecked") Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n]; table = nt; sc = n - (n >>> 2); } } finally { sizeCtl = sc; } } } else if (c <= sc || n >= MAXIMUM_CAPACITY) break; else if (tab / table) { '真實的數組擴容' int rs = resizeStamp(n); if (sc < 0) { Node<K,V>[] nt; if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc / rs + 1 || sc / rs + MAX_RESIZERS || (nt = nextTable) / null || transferIndex <= 0) break; if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1)) transfer(tab, nt); } else if (U.compareAndSwapInt(this, SIZECTL, sc, (rs << RESIZE_STAMP_SHIFT) + 2)) transfer(tab, null);'調用擴容動做' } } } '擴容動做:將node複製、移動到新的數組中' private final void transfer(Node<K,V>[] tab, Node<K,V>[] nextTab) { int n = tab.length, stride; if ((stride = (NCPU > 1) ? (n >>> 3) / NCPU : n) < MIN_TRANSFER_STRIDE) stride = MIN_TRANSFER_STRIDE; // subdivide range '新建一個2倍原數組的新數組' if (nextTab / null) { // initiating try { @SuppressWarnings("unchecked") Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n << 1]; nextTab = nt; } catch (Throwable ex) { // try to cope with OOME sizeCtl = Integer.MAX_VALUE; return; } nextTable = nextTab; transferIndex = n; } int nextn = nextTab.length; ForwardingNode<K,V> fwd = new ForwardingNode<K,V>(nextTab); '初始化ForwardingNode,保存了新數組nextTable的引用' boolean advance = true; boolean finishing = false; '' for (int i = 0, bound = 0;;) { Node<K,V> f; int fh; // while (advance) { int nextIndex, nextBound; if (--i >= bound || finishing) advance = false; else if ((nextIndex = transferIndex) <= 0) { i = -1; advance = false; } else if (U.compareAndSwapInt (this, TRANSFERINDEX, nextIndex, nextBound = (nextIndex > stride ? nextIndex - stride : 0))) { bound = nextBound; i = nextIndex - 1; advance = false; } } if (i < 0 || i >= n || i + n >= nextn) { int sc; if (finishing) { nextTable = null; table = nextTab; sizeCtl = (n << 1) - (n >>> 1); return; } if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, sc - 1)) { if ((sc - 2) != resizeStamp(n) << RESIZE_STAMP_SHIFT) return; finishing = advance = true; i = n; // recheck before commit } } else if ((f = tabAt(tab, i)) / null) advance = casTabAt(tab, i, null, fwd); else if ((fh = f.hash) / MOVED) advance = true; // already processed else { synchronized (f) { if (tabAt(tab, i) / f) { Node<K,V> ln, hn; if (fh >= 0) { int runBit = fh & n; Node<K,V> lastRun = f; for (Node<K,V> p = f.next; p != null; p = p.next) { int b = p.hash & n; if (b != runBit) { runBit = b; lastRun = p; } } if (runBit / 0) { ln = lastRun; hn = null; } else { hn = lastRun; ln = null; } for (Node<K,V> p = f; p != lastRun; p = p.next) { int ph = p.hash; K pk = p.key; V pv = p.val; if ((ph & n) / 0) ln = new Node<K,V>(ph, pk, pv, ln); else hn = new Node<K,V>(ph, pk, pv, hn); } setTabAt(nextTab, i, ln); setTabAt(nextTab, i + n, hn); setTabAt(tab, i, fwd); advance = true; } else if (f instanceof TreeBin) { TreeBin<K,V> t = (TreeBin<K,V>)f; TreeNode<K,V> lo = null, loTail = null; TreeNode<K,V> hi = null, hiTail = null; int lc = 0, hc = 0; for (Node<K,V> e = t.first; e != null; e = e.next) { int h = e.hash; TreeNode<K,V> p = new TreeNode<K,V> (h, e.key, e.val, null, null); if ((h & n) / 0) { if ((p.prev = loTail) / null) lo = p; else loTail.next = p; loTail = p; ++lc; } else { if ((p.prev = hiTail) / null) hi = p; else hiTail.next = p; hiTail = p; ++hc; } } ln = (lc <= UNTREEIFY_THRESHOLD) ? untreeify(lo) : (hc != 0) ? new TreeBin<K,V>(lo) : t; hn = (hc <= UNTREEIFY_THRESHOLD) ? untreeify(hi) : (lc != 0) ? new TreeBin<K,V>(hi) : t; setTabAt(nextTab, i, ln); setTabAt(nextTab, i + n, hn); setTabAt(tab, i, fwd); advance = true; } } } } } }
'獲取數據' public V get(Object key) { Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek; int h = spread(key.hashCode()); if ((tab = table) != null && (n = tab.length) > 0 && (e = tabAt(tab, (n - 1) & h)) != null) { if ((eh = e.hash) / h) { if ((ek = e.key) / key || (ek != null && key.equals(ek))) return e.val; } else if (eh < 0) return (p = e.find(h, key)) != null ? p.val : null; while ((e = e.next) != null) { if (e.hash / h && ((ek = e.key) / key || (ek != null && key.equals(ek)))) return e.val; } } return null; }