Java7/8 涓?HashMap 鍜?ConcurrentHashMap婧愮爜瀵规瘮鍒嗘瀽

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java7/8 涓?HashMap 鍜?ConcurrentHashMap婧愮爜瀵规瘮鍒嗘瀽相关的知识,希望对你有一定的参考价值。

鏍囩锛?a href='http://www.mamicode.com/so/1/ide' title='ide'>ide   鍏磋叮   瓒呰繃   鐩存帴   rem   math   鏂囩珷   equal   ast   

缃戜笂鍏充簬 HashMap 鍜?ConcurrentHashMap 鐨勬枃绔犵‘瀹炰笉灏戯紝涓嶈繃缂烘枻灏戜袱鐨勬枃绔犳瘮杈冨锛屾墍浠ユ墠鎯宠嚜宸变篃鍐欎竴绡囷紝鎶婄粏鑺傝娓呮璇撮€忥紝灏ゅ叾鍍?Java8 涓殑 ConcurrentHashMap锛屽ぇ閮ㄥ垎鏂囩珷閮借涓嶆竻妤氥€傜粓褰掓槸甯屾湜鑳介檷浣庡ぇ瀹跺涔犵殑鎴愭湰锛屼笉甯屾湜澶у鍒板鎵惧悇绉嶄笉鏄緢闈犺氨鐨勬枃绔狅紝鐪嬪畬涓€绡囧張涓€绡囷紝鍙槸杩樻槸妯℃ā绯婄硦銆?/p>

闃呰寤鸿锛氬洓鑺傚熀鏈笂鍙互杩涜鐙珛闃呰锛屽缓璁垵瀛﹁€呭彲鎸夌収 Java7 HashMap -> Java7 ConcurrentHashMap -> Java8 HashMap -> Java8 ConcurrentHashMap 椤哄簭杩涜闃呰锛屽彲閫傚綋闄嶄綆闃呰闂ㄦ銆?/p>

闃呰鍓嶆彁锛氭湰鏂囧垎鏋愮殑鏄簮鐮侊紝鎵€浠ヨ嚦灏戣鑰呰鐔熸倝瀹冧滑鐨勬帴鍙d娇鐢紝鍚屾椂锛屽浜庡苟鍙戯紝璇昏€呰嚦灏戣鐭ラ亾 CAS銆丷eentrantLock銆乁NSAFE 鎿嶄綔杩欏嚑涓熀鏈殑鐭ヨ瘑锛屾枃涓笉浼氬杩欎簺鐭ヨ瘑杩涜浠嬬粛銆侸ava8 鐢ㄥ埌浜嗙孩榛戞爲锛屼笉杩囨湰鏂囦笉浼氳繘琛屽睍寮€锛屾劅鍏磋叮鐨勮鑰呰鑷鏌ユ壘鐩稿叧璧勬枡銆?/p>

Java7 HashMap

HashMap 鏄渶绠€鍗曠殑锛屼竴鏉ユ垜浠潪甯哥啛鎮夛紝浜屾潵灏辨槸瀹冧笉鏀寔骞跺彂鎿嶄綔锛屾墍浠ユ簮鐮佷篃闈炲父绠€鍗曘€?/p>

棣栧厛锛屾垜浠敤涓嬮潰杩欏紶鍥炬潵浠嬬粛 HashMap 鐨勭粨鏋勩€?/p>

鎶€鏈垎浜浘鐗? src=

杩欎釜浠呬粎鏄ず鎰忓浘锛屽洜涓烘病鏈夎€冭檻鍒版暟缁勮鎵╁鐨勬儏鍐碉紝鍏蜂綋鐨勫悗闈㈠啀璇淬€?/p>

澶ф柟鍚戜笂锛孒ashMap 閲岄潰鏄竴涓暟缁勶紝鐒跺悗鏁扮粍涓瘡涓厓绱犳槸涓€涓崟鍚戦摼琛ㄣ€?/p>

涓婂浘涓紝姣忎釜缁胯壊鐨勫疄浣撴槸宓屽绫?Entry 鐨勫疄渚嬶紝Entry 鍖呭惈鍥涗釜灞炴€э細key, value, hash 鍊煎拰鐢ㄤ簬鍗曞悜閾捐〃鐨?next銆?/p>

capacity锛氬綋鍓嶆暟缁勫閲忥紝濮嬬粓淇濇寔 2^n锛屽彲浠ユ墿瀹癸紝鎵╁鍚庢暟缁勫ぇ灏忎负褰撳墠鐨?2 鍊嶃€?/p>

loadFactor锛氳礋杞藉洜瀛愶紝榛樿涓?0.75銆?/p>

threshold锛氭墿瀹圭殑闃堝€硷紝绛変簬 capacity * loadFactor

put 杩囩▼鍒嗘瀽

杩樻槸姣旇緝绠€鍗曠殑锛岃窡鐫€浠g爜璧颁竴閬嶅惂銆?/p>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public V put(K key, V value) {
    // 褰撴彃鍏ョ涓€涓厓绱犵殑鏃跺€欙紝闇€瑕佸厛鍒濆鍖栨暟缁勫ぇ灏?/code>
    if (table == EMPTY_TABLE) {
        inflateTable(threshold);
    }
    // 濡傛灉 key 涓?null锛屾劅鍏磋叮鐨勫彲浠ュ線閲岀湅锛屾渶缁堜細灏嗚繖涓?entry 鏀惧埌 table[0] 涓?/code>
    if (key == null)
        return putForNullKey(value);
    // 1. 姹?key 鐨?hash 鍊?/code>
    int hash = hash(key);
    // 2. 鎵惧埌瀵瑰簲鐨勬暟缁勪笅鏍?/code>
    int i = indexFor(hash, table.length);
    // 3. 閬嶅巻涓€涓嬪搴斾笅鏍囧鐨勯摼琛紝鐪嬫槸鍚︽湁閲嶅鐨?key 宸茬粡瀛樺湪锛?/code>
    //    濡傛灉鏈夛紝鐩存帴瑕嗙洊锛宲ut 鏂规硶杩斿洖鏃у€煎氨缁撴潫浜?/code>
    for (Entry<K,V> e = table[i]; e != null; e = e.next) {
        Object k;
        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
            V oldValue = e.value;
            e.value = value;
            e.recordAccess(this);
            return oldValue;
        }
    }
 
    modCount++;
    // 4. 涓嶅瓨鍦ㄩ噸澶嶇殑 key锛屽皢姝?entry 娣诲姞鍒伴摼琛ㄤ腑锛岀粏鑺傚悗闈㈣
    addEntry(hash, key, value, i);
    return null;
}

鏁扮粍鍒濆鍖?/h4>

鍦ㄧ涓€涓厓绱犳彃鍏?HashMap 鐨勬椂鍊欏仛涓€娆℃暟缁勭殑鍒濆鍖栵紝灏辨槸鍏堢‘瀹氬垵濮嬬殑鏁扮粍澶у皬锛屽苟璁$畻鏁扮粍鎵╁鐨勯槇鍊笺€?/p>

1
2
3
4
5
6
7
8
9
10
private void inflateTable(int toSize) {
    // 淇濊瘉鏁扮粍澶у皬涓€瀹氭槸 2 鐨?n 娆℃柟銆?/code>
    // 姣斿杩欐牱鍒濆鍖栵細new HashMap(20)锛岄偅涔堝鐞嗘垚鍒濆鏁扮粍澶у皬鏄?32
    int capacity = roundUpToPowerOf2(toSize);
    // 璁$畻鎵╁闃堝€硷細capacity * loadFactor
    threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
    // 绠楁槸鍒濆鍖栨暟缁勫惂
    table = new Entry[capacity];
    initHashSeedAsNeeded(capacity); //ignore
}

杩欓噷鏈変竴涓皢鏁扮粍澶у皬淇濇寔涓?2 鐨?n 娆℃柟鐨勫仛娉曪紝Java7 鍜?Java8 鐨?HashMap 鍜?ConcurrentHashMap 閮芥湁鐩稿簲鐨勮姹傦紝鍙笉杩囧疄鐜扮殑浠g爜绋嶅井鏈変簺涓嶅悓锛屽悗闈㈠啀鐪嬪埌鐨勬椂鍊欏氨鐭ラ亾浜嗐€?/p>

璁$畻鍏蜂綋鏁扮粍浣嶇疆

杩欎釜绠€鍗曪紝鎴戜滑鑷繁涔熻兘 YY 涓€涓細浣跨敤 key 鐨?hash 鍊煎鏁扮粍闀垮害杩涜鍙栨ā灏卞彲浠ヤ簡銆?/p>

1
2
3
4
static int indexFor(int hash, int length) {
    // assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2";
    return hash & (length-1);
}

杩欎釜鏂规硶寰堢畝鍗曪紝绠€鍗曡灏辨槸鍙?hash 鍊肩殑浣?n 浣嶃€傚鍦ㄦ暟缁勯暱搴︿负 32 鐨勬椂鍊欙紝鍏跺疄鍙栫殑灏辨槸 key 鐨?hash 鍊肩殑浣?5 浣嶏紝浣滀负瀹冨湪鏁扮粍涓殑涓嬫爣浣嶇疆銆?/p>

娣诲姞鑺傜偣鍒伴摼琛ㄤ腑

鎵惧埌鏁扮粍涓嬫爣鍚庯紝浼氬厛杩涜 key 鍒ら噸锛屽鏋滄病鏈夐噸澶嶏紝灏卞噯澶囧皢鏂板€兼斁鍏ュ埌閾捐〃鐨勮〃澶淬€?/p>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void addEntry(int hash, K key, V value, int bucketIndex) {
    // 濡傛灉褰撳墠 HashMap 澶у皬宸茬粡杈惧埌浜嗛槇鍊硷紝骞朵笖鏂板€艰鎻掑叆鐨勬暟缁勪綅缃凡缁忔湁鍏冪礌浜嗭紝閭d箞瑕佹墿瀹?/code>
    if ((size >= threshold) && (null != table[bucketIndex])) {
        // 鎵╁锛屽悗闈細浠嬬粛涓€涓?/code>
        resize(2 * table.length);
        // 鎵╁浠ュ悗锛岄噸鏂拌绠?hash 鍊?/code>
        hash = (null != key) ? hash(key) : 0;
        // 閲嶆柊璁$畻鎵╁鍚庣殑鏂扮殑涓嬫爣
        bucketIndex = indexFor(hash, table.length);
    }
    // 寰€涓嬬湅
    createEntry(hash, key, value, bucketIndex);
}
// 杩欎釜寰堢畝鍗曪紝鍏跺疄灏辨槸灏嗘柊鍊兼斁鍒伴摼琛ㄧ殑琛ㄥご锛岀劧鍚?size++
void createEntry(int hash, K key, V value, int bucketIndex) {
    Entry<K,V> e = table[bucketIndex];
    table[bucketIndex] = new Entry<>(hash, key, value, e);
    size++;
}

杩欎釜鏂规硶鐨勪富瑕侀€昏緫灏辨槸鍏堝垽鏂槸鍚﹂渶瑕佹墿瀹癸紝闇€瑕佺殑璇濆厛鎵╁锛岀劧鍚庡啀灏嗚繖涓柊鐨勬暟鎹彃鍏ュ埌鎵╁鍚庣殑鏁扮粍鐨勭浉搴斾綅缃鐨勯摼琛ㄧ殑琛ㄥご銆?/p>

鏁扮粍鎵╁

鍓嶉潰鎴戜滑鐪嬪埌锛屽湪鎻掑叆鏂板€肩殑鏃跺€欙紝濡傛灉褰撳墠鐨?size 宸茬粡杈惧埌浜嗛槇鍊硷紝骞朵笖瑕佹彃鍏ョ殑鏁扮粍浣嶇疆涓婂凡缁忔湁鍏冪礌锛岄偅涔堝氨浼氳Е鍙戞墿瀹癸紝鎵╁鍚庯紝鏁扮粍澶у皬涓哄師鏉ョ殑 2 鍊嶃€?/p>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void resize(int newCapacity) {
    Entry[] oldTable = table;
    int oldCapacity = oldTable.length;
    if (oldCapacity == MAXIMUM_CAPACITY) {
        threshold = Integer.MAX_VALUE;
        return;
    }
    // 鏂扮殑鏁扮粍
    Entry[] newTable = new Entry[newCapacity];
    // 灏嗗師鏉ユ暟缁勪腑鐨勫€艰縼绉诲埌鏂扮殑鏇村ぇ鐨勬暟缁勪腑
    transfer(newTable, initHashSeedAsNeeded(newCapacity));
    table = newTable;
    threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
}

鎵╁灏辨槸鐢ㄤ竴涓柊鐨勫ぇ鏁扮粍鏇挎崲鍘熸潵鐨勫皬鏁扮粍锛屽苟灏嗗師鏉ユ暟缁勪腑鐨勫€艰縼绉诲埌鏂扮殑鏁扮粍涓€?/p>

鐢变簬鏄弻鍊嶆墿瀹癸紝杩佺Щ杩囩▼涓紝浼氬皢鍘熸潵 table[i] 涓殑閾捐〃鐨勬墍鏈夎妭鐐癸紝鍒嗘媶鍒版柊鐨勬暟缁勭殑 newTable[i] 鍜?newTable[i + oldLength] 浣嶇疆涓娿€傚鍘熸潵鏁扮粍闀垮害鏄?16锛岄偅涔堟墿瀹瑰悗锛屽師鏉?table[0] 澶勭殑閾捐〃涓殑鎵€鏈夊厓绱犱細琚垎閰嶅埌鏂版暟缁勪腑 newTable[0] 鍜?newTable[16] 杩欎袱涓綅缃€備唬鐮佹瘮杈冪畝鍗曪紝杩欓噷灏变笉灞曞紑浜嗐€?/p>

get 杩囩▼鍒嗘瀽

鐩稿浜?put 杩囩▼锛実et 杩囩▼鏄潪甯哥畝鍗曠殑銆?/p>

  1. 鏍规嵁 key 璁$畻 hash 鍊笺€?/li>
  2. 鎵惧埌鐩稿簲鐨勬暟缁勪笅鏍囷細hash & (length 鈥?1)銆?/li>
  3. 閬嶅巻璇ユ暟缁勪綅缃鐨勯摼琛紝鐩村埌鎵惧埌鐩哥瓑(==鎴杄quals)鐨?key銆?/li>
1
2
3
4
5
6
7
8
9
public V get(Object key) {
    // 涔嬪墠璇磋繃锛宬ey 涓?null 鐨勮瘽锛屼細琚斁鍒?table[0]锛屾墍浠ュ彧瑕侀亶鍘嗕笅 table[0] 澶勭殑閾捐〃灏卞彲浠ヤ簡
    if (key == null)
        return getForNullKey();
    //
    Entry<K,V> entry = getEntry(key);
 
    return null == entry ? null : entry.getValue();
}

getEntry(key):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
final Entry<K,V> getEntry(Object key) {
    if (size == 0) {
        return null;
    }
 
    int hash = (key == null) ? 0 : hash(key);
    // 纭畾鏁扮粍涓嬫爣锛岀劧鍚庝粠澶村紑濮嬮亶鍘嗛摼琛紝鐩村埌鎵惧埌涓烘
    for (Entry<K,V> e = table[indexFor(hash, table.length)];
         e != null;
         e = e.next) {
        Object k;
        if (e.hash == hash &&
            ((k = e.key) == key || (key != null && key.equals(k))))
            return e;
    }
    return null;
}

Java7 ConcurrentHashMap

ConcurrentHashMap 鍜?HashMap 鎬濊矾鏄樊涓嶅鐨勶紝浣嗘槸鍥犱负瀹?span style="background-color: #ff9900">鏀寔骞跺彂鎿嶄綔锛屾墍浠ヨ澶嶆潅涓€浜涖€?/p>

鏁翠釜 ConcurrentHashMap 鐢变竴涓釜 Segment 缁勬垚锛孲egment 浠h〃鈥濋儴鍒嗏€滄垨鈥濅竴娈碘€滅殑鎰忔€濓紝鎵€浠ュ緢澶氬湴鏂归兘浼氬皢鍏舵弿杩颁负鍒嗘閿併€傛敞鎰忥紝琛屾枃涓紝鎴戝緢澶氬湴鏂圭敤浜嗏€滄Ы鈥濇潵浠h〃涓€涓?segment銆?/p>

绠€鍗曠悊瑙e氨鏄紝ConcurrentHashMap 鏄竴涓?Segment 鏁扮粍锛孲egment 閫氳繃缁ф壙 ReentrantLock 鏉ヨ繘琛屽姞閿侊紝鎵€浠ユ瘡娆¢渶瑕佸姞閿佺殑鎿嶄綔閿佷綇鐨勬槸涓€涓?segment锛岃繖鏍峰彧瑕佷繚璇佹瘡涓?Segment 鏄嚎绋嬪畨鍏ㄧ殑锛屼篃灏卞疄鐜颁簡鍏ㄥ眬鐨勭嚎绋嬪畨鍏ㄣ€?/p>

鎶€鏈垎浜浘鐗? src=

concurrencyLevel锛氬苟琛岀骇鍒€佸苟鍙戞暟銆丼egment 鏁帮紝鎬庝箞缈昏瘧涓嶉噸瑕侊紝鐞嗚В瀹冦€傞粯璁ゆ槸 16锛屼篃灏辨槸璇?ConcurrentHashMap 鏈?16 涓?Segments锛屾墍浠ョ悊璁轰笂锛岃繖涓椂鍊欙紝鏈€澶氬彲浠ュ悓鏃舵敮鎸?16 涓嚎绋嬪苟鍙戝啓锛屽彧瑕佸畠浠殑鎿嶄綔鍒嗗埆鍒嗗竷鍦ㄤ笉鍚岀殑 Segment 涓娿€傝繖涓€煎彲浠ュ湪鍒濆鍖栫殑鏃跺€欒缃负鍏朵粬鍊硷紝浣嗘槸涓€鏃﹀垵濮嬪寲浠ュ悗锛屽畠鏄笉鍙互鎵╁鐨勩€?/p>

鍐嶅叿浣撳埌姣忎釜 Segment 鍐呴儴锛?span style="color: #ff0000">鍏跺疄姣忎釜 Segment 寰堝儚涔嬪墠浠嬬粛鐨?HashMap锛屼笉杩囧畠瑕佷繚璇佺嚎绋嬪畨鍏紝鎵€浠ュ鐞嗚捣鏉ヨ楹荤儲浜?/span>銆?/p>

鍒濆鍖?/h3>

initialCapacity锛氬垵濮嬪閲忥紝杩欎釜鍊兼寚鐨勬槸鏁翠釜 ConcurrentHashMap 鐨勫垵濮嬪閲忥紝瀹為檯鎿嶄綔鐨勬椂鍊欓渶瑕佸钩鍧囧垎缁欐瘡涓?Segment銆?/p>

loadFactor锛氳礋杞藉洜瀛愶紝涔嬪墠鎴戜滑璇翠簡锛孲egment 鏁扮粍涓嶅彲浠ユ墿瀹癸紝鎵€浠ヨ繖涓礋杞藉洜瀛愭槸缁欐瘡涓?Segment 鍐呴儴浣跨敤鐨勩€?/p>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public ConcurrentHashMap(int initialCapacity,
                         float loadFactor, int concurrencyLevel) {
    if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0)
        throw new IllegalArgumentException();
    if (concurrencyLevel > MAX_SEGMENTS)
        concurrencyLevel = MAX_SEGMENTS;
    // Find power-of-two sizes best matching arguments
    int sshift = 0;
    int ssize = 1;
    // 璁$畻骞惰绾у埆 ssize锛屽洜涓鸿淇濇寔骞惰绾у埆鏄?2 鐨?n 娆℃柟
    while (ssize < concurrencyLevel) {
        ++sshift;
        ssize <<= 1;
    }
    // 鎴戜滑杩欓噷鍏堜笉瑕侀偅涔堢儳鑴戯紝鐢ㄩ粯璁ゅ€硷紝concurrencyLevel 涓?16锛宻shift 涓?4
    // 閭d箞璁$畻鍑?segmentShift 涓?28锛宻egmentMask 涓?15锛屽悗闈細鐢ㄥ埌杩欎袱涓€?/code>
    this.segmentShift = 32 - sshift;
    this.segmentMask = ssize - 1;
 
    if (initialCapacity > MAXIMUM_CAPACITY)
        initialCapacity = MAXIMUM_CAPACITY;
 
    // initialCapacity 鏄缃暣涓?map 鍒濆鐨勫ぇ灏忥紝
    // 杩欓噷鏍规嵁 initialCapacity 璁$畻 Segment 鏁扮粍涓瘡涓綅缃彲浠ュ垎鍒扮殑澶у皬
    // 濡?initialCapacity 涓?64锛岄偅涔堟瘡涓?Segment 鎴栫О涔嬩负"妲?鍙互鍒嗗埌 4 涓?/code>
    int c = initialCapacity / ssize;
    if (c * ssize < initialCapacity)
        ++c;
    // 榛樿 MIN_SEGMENT_TABLE_CAPACITY 鏄?2锛岃繖涓€间篃鏄湁璁茬┒鐨勶紝鍥犱负杩欐牱鐨勮瘽锛屽浜庡叿浣撶殑妲戒笂锛?/code>
    // 鎻掑叆涓€涓厓绱犱笉鑷充簬鎵╁锛屾彃鍏ョ浜屼釜鐨勬椂鍊欐墠浼氭墿瀹?/code>
    int cap = MIN_SEGMENT_TABLE_CAPACITY;
    while (cap < c)
        cap <<= 1;
 
    // 鍒涘缓 Segment 鏁扮粍锛?/code>
    // 骞跺垱寤烘暟缁勭殑绗竴涓厓绱?segment[0]
    Segment<K,V> s0 =
        new Segment<K,V>(loadFactor, (int)(cap * loadFactor),
                         (HashEntry<K,V>[])new HashEntry[cap]);
    Segment<K,V>[] ss = (Segment<K,V>[])new Segment[ssize];
    // 寰€鏁扮粍鍐欏叆 segment[0]
    UNSAFE.putOrderedObject(ss, SBASE, s0); // ordered write of segments[0]
    this.segments = ss;
}

鍒濆鍖栧畬鎴愶紝鎴戜滑寰楀埌浜嗕竴涓?Segment 鏁扮粍銆?/p>

鎴戜滑灏卞綋鏄敤 new ConcurrentHashMap() 鏃犲弬鏋勯€犲嚱鏁拌繘琛屽垵濮嬪寲鐨勶紝閭d箞鍒濆鍖栧畬鎴愬悗锛?/p>

  • Segment 鏁扮粍闀垮害涓?16锛屼笉鍙互鎵╁
  • Segment[i] 鐨勯粯璁ゅぇ灏忎负 2锛岃礋杞藉洜瀛愭槸 0.75锛屽緱鍑哄垵濮嬮槇鍊间负 1.5锛屼篃灏辨槸浠ュ悗鎻掑叆绗竴涓厓绱犱笉浼氳Е鍙戞墿瀹癸紝鎻掑叆绗簩涓細杩涜绗竴娆℃墿瀹?/li>
  • 杩欓噷鍒濆鍖栦簡 segment[0]锛屽叾浠栦綅缃繕鏄?null锛岃嚦浜庝负浠€涔堣鍒濆鍖?segment[0]锛屽悗闈㈢殑浠g爜浼氫粙缁?/li>
  • 褰撳墠 segmentShift 鐨勫€间负 32 鈥?4 = 28锛宻egmentMask 涓?16 鈥?1 = 15锛屽涓旀妸瀹冧滑绠€鍗曠炕璇戜负绉讳綅鏁板拰鎺╃爜锛岃繖涓や釜鍊奸┈涓婂氨浼氱敤鍒?/li>

put 杩囩▼鍒嗘瀽

鎴戜滑鍏堢湅 put 鐨勪富娴佺▼锛屽浜庡叾涓殑涓€浜涘叧閿粏鑺傛搷浣滐紝鍚庨潰浼氳繘琛岃缁嗕粙缁嶃€?/p>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public V put(K key, V value) {
    Segment<K,V> s;
    if (value == null)
        throw new NullPointerException();
    // 1. 璁$畻 key 鐨?hash 鍊?/code>
    int hash = hash(key);
    // 2. 鏍规嵁 hash 鍊兼壘鍒?Segment 鏁扮粍涓殑浣嶇疆 j
    //    hash 鏄?32 浣嶏紝鏃犵鍙峰彸绉?segmentShift(28) 浣嶏紝鍓╀笅浣?4 浣嶏紝
    //    鐒跺悗鍜?segmentMask(15) 鍋氫竴娆′笌鎿嶄綔锛屼篃灏辨槸璇?j 鏄?hash 鍊肩殑鏈€鍚?4 浣嶏紝涔熷氨鏄Ы鐨勬暟缁勪笅鏍?/code>
    int j = (hash >>> segmentShift) & segmentMask;
    // 鍒氬垰璇翠簡锛屽垵濮嬪寲鐨勬椂鍊欏垵濮嬪寲浜?segment[0]锛屼絾鏄叾浠栦綅缃繕鏄?null锛?/code>
    // ensureSegment(j) 瀵?segment[j] 杩涜鍒濆鍖?/code>
    if ((s = (Segment<K,V>)UNSAFE.getObject          // nonvolatile; recheck
         (segments, (j << SSHIFT) + SBASE)) == null) //  in ensureSegment
        s = ensureSegment(j);
    // 3. 鎻掑叆鏂板€煎埌 妲?s 涓?/code>
    return s.put(key, hash, value, false);
}

绗竴灞傜毊寰堢畝鍗曪紝鏍规嵁 hash 鍊煎緢蹇氨鑳芥壘鍒扮浉搴旂殑 Segment锛屼箣鍚庡氨鏄?Segment 鍐呴儴鐨?put 鎿嶄綔浜嗐€?/p>

Segment 鍐呴儴鏄敱 鏁扮粍+閾捐〃 缁勬垚鐨勩€?/p>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
final V put(K key, int hash, V value, boolean onlyIfAbsent) {
    // 鍦ㄥ線璇?segment 鍐欏叆鍓嶏紝闇€瑕佸厛鑾峰彇璇?segment 鐨勭嫭鍗犻攣
    //    鍏堢湅涓绘祦绋嬶紝鍚庨潰杩樹細鍏蜂綋浠嬬粛杩欓儴鍒嗗唴瀹?/code>
    HashEntry<K,V> node = tryLock() ? null :
        scanAndLockForPut(key, hash, value);
    V oldValue;
    try {
        // 杩欎釜鏄?segment 鍐呴儴鐨勬暟缁?/code>
        HashEntry<K,V>[] tab = table;
        // 鍐嶅埄鐢?hash 鍊硷紝姹傚簲璇ユ斁缃殑鏁扮粍涓嬫爣
        int index = (tab.length - 1) & hash;
        // first 鏄暟缁勮浣嶇疆澶勭殑閾捐〃鐨勮〃澶?/code>
        HashEntry<K,V> first = entryAt(tab, index);
 
        // 涓嬮潰杩欎覆 for 寰幆铏界劧寰堥暱锛屼笉杩囦篃寰堝ソ鐞嗚В锛屾兂鎯宠浣嶇疆娌℃湁浠讳綍鍏冪礌鍜屽凡缁忓瓨鍦ㄤ竴涓摼琛ㄨ繖涓ょ鎯呭喌
        for (HashEntry<K,V> e = first;;) {
            if (e != null) {
                K k;
                if ((k = e.key) == key ||
                    (e.hash == hash && key.equals(k))) {
                    oldValue = e.value;
                    if (!onlyIfAbsent) {
                        // 瑕嗙洊鏃у€?/code>
                        e.value = value;
                        ++modCount;
                    }
                    break;
                }
                // 缁х画椤虹潃閾捐〃璧?/code>
                e = e.next;
            }
            else {
                // node 鍒板簳鏄笉鏄?null锛岃繖涓鐪嬭幏鍙栭攣鐨勮繃绋嬶紝涓嶈繃鍜岃繖閲岄兘娌℃湁鍏崇郴銆?/code>
                // 濡傛灉涓嶄负 null锛岄偅灏辩洿鎺ュ皢瀹冭缃负閾捐〃琛ㄥご锛涘鏋滄槸null锛屽垵濮嬪寲骞惰缃负閾捐〃琛ㄥご銆?/code>
                if (node != null)
                    node.setNext(first);
                else
                    node = new HashEntry<K,V>(hash, key, value, first);
 
                int c = count + 1;
                // 濡傛灉瓒呰繃浜嗚 segment 鐨勯槇鍊硷紝杩欎釜 segment 闇€瑕佹墿瀹?/code>
                if (c > threshold && tab.length < MAXIMUM_CAPACITY)
                    rehash(node); // 鎵╁鍚庨潰涔熶細鍏蜂綋鍒嗘瀽
                else
                    // 娌℃湁杈惧埌闃堝€硷紝灏?node 鏀惧埌鏁扮粍 tab 鐨?index 浣嶇疆锛?/code>
                    // 鍏跺疄灏辨槸灏嗘柊鐨勮妭鐐硅缃垚鍘熼摼琛ㄧ殑琛ㄥご
                    setEntryAt(tab, index, node);
                ++modCount;
                count = c;
                oldValue = null;
                break;
            }
        }
    } finally {
        // 瑙i攣
        unlock();
    }
    return oldValue;
}

鏁翠綋娴佺▼杩樻槸姣旇緝绠€鍗曠殑锛岀敱浜庢湁鐙崰閿佺殑淇濇姢锛屾墍浠?segment 鍐呴儴鐨勬搷浣滃苟涓嶅鏉傘€傝嚦浜庤繖閲岄潰鐨勫苟鍙戦棶棰橈紝鎴戜滑绋嶅悗鍐嶈繘琛屼粙缁嶃€?/p>

鍒拌繖閲?put 鎿嶄綔灏辩粨鏉熶簡锛屾帴涓嬫潵锛屾垜浠涓€璇村叾涓嚑姝ュ叧閿殑鎿嶄綔銆?/p>

鍒濆鍖栨Ы: ensureSegment

ConcurrentHashMap 鍒濆鍖栫殑鏃跺€欎細鍒濆鍖栫涓€涓Ы segment[0]锛屽浜庡叾浠栨Ы鏉ヨ锛屽湪鎻掑叆绗竴涓€肩殑鏃跺€欒繘琛屽垵濮嬪寲銆?/p>

杩欓噷闇€瑕佽€冭檻骞跺彂锛屽洜涓哄緢鍙兘浼氭湁澶氫釜绾跨▼鍚屾椂杩涙潵鍒濆鍖栧悓涓€涓Ы segment[k]锛屼笉杩囧彧瑕佹湁涓€涓垚鍔熶簡灏卞彲浠ャ€?/p>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private Segment<K,V> ensureSegment(int k) {
    final Segment<K,V>[] ss = this.segments;
    long u = (k << SSHIFT) + SBASE; // raw offset
    Segment<K,V> seg;
    if ((seg = (Segment<K,V>)UNSAFE.getObjectVolatile(ss, u)) == null) {
        // 杩欓噷鐪嬪埌涓轰粈涔堜箣鍓嶈鍒濆鍖?segment[0] 浜嗭紝
        // 浣跨敤褰撳墠 segment[0] 澶勭殑鏁扮粍闀垮害鍜岃礋杞藉洜瀛愭潵鍒濆鍖?segment[k]
        // 涓轰粈涔堣鐢ㄢ€滃綋鍓嶁€濓紝鍥犱负 segment[0] 鍙兘鏃╁氨鎵╁杩囦簡
        Segment<K,V> proto = ss[0];
        int cap = proto.table.length;
        float lf = proto.loadFactor;
        int threshold = (int)(cap * lf);
 
        // 鍒濆鍖?segment[k] 鍐呴儴鐨勬暟缁?/code>
        HashEntry<K,V>[] tab = (HashEntry<K,V>[])new HashEntry[cap];
        if ((seg = (Segment<K,V>)UNSAFE.getObjectVolatile(ss, u))
            == null) { // 鍐嶆妫€鏌ヤ竴閬嶈妲芥槸鍚﹁鍏朵粬绾跨▼鍒濆鍖栦簡銆?/code>
 
            Segment<K,V> s = new Segment<K,V>(lf, threshold, tab);
            // 浣跨敤 while 寰幆锛屽唴閮ㄧ敤 CAS锛屽綋鍓嶇嚎绋嬫垚鍔熻鍊兼垨鍏朵粬绾跨▼鎴愬姛璁惧€煎悗锛岄€€鍑?/code>
            while ((seg = (Segment<K,V>)UNSAFE.getObjectVolatile(ss, u))
                   == null) {
                if (UNSAFE.compareAndSwapObject(ss, u, null, seg = s))
                    break;
            }
        }
    }
    return seg;
}

鎬荤殑鏉ヨ锛宔nsureSegment(int k) 姣旇緝绠€鍗曪紝瀵逛簬骞跺彂鎿嶄綔浣跨敤 CAS 杩涜鎺у埗銆?/p>

鎴戞病鎼炴噦杩欓噷涓轰粈涔堣鎼炰竴涓?while 寰幆锛孋AS 澶辫触涓嶅氨浠h〃鏈夊叾浠栫嚎绋嬫垚鍔熶簡鍚楋紝涓轰粈涔堣鍐嶈繘琛屽垽鏂紵

鑾峰彇鍐欏叆閿? scanAndLockForPut

鍓嶉潰鎴戜滑鐪嬪埌锛屽湪寰€鏌愪釜 segment 涓?put 鐨勬椂鍊欙紝棣栧厛浼氳皟鐢?node = tryLock() ? null : scanAndLockForPut(key, hash, value)锛屼篃灏辨槸璇村厛杩涜涓€娆?tryLock() 蹇€熻幏鍙栬 segment 鐨勭嫭鍗犻攣锛屽鏋滃け璐ワ紝閭d箞杩涘叆鍒?scanAndLockForPut 杩欎釜鏂规硶鏉ヨ幏鍙栭攣銆?/p>

涓嬮潰鎴戜滑鏉ュ叿浣撳垎鏋愯繖涓柟娉曚腑鏄€庝箞鎺у埗鍔犻攣鐨勩€?/p>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
private HashEntry<K,V> scanAndLockForPut(K key, int hash, V value) {
    HashEntry<K,V> first = entryForHash(this, hash);
    HashEntry<K,V> e = first;
    HashEntry<K,V> node = null;
    int retries = -1; // negative while locating node
 
    // 寰幆鑾峰彇閿?/code>
    while (!tryLock()) {
        HashEntry<K,V> f; // to recheck first below
        if (retries < 0) {
            if (e == null) {
                if (node == null) // speculatively create node
                    // 杩涘埌杩欓噷璇存槑鏁扮粍璇ヤ綅缃殑閾捐〃鏄┖鐨勶紝娌℃湁浠讳綍鍏冪礌
                    // 褰撶劧锛岃繘鍒拌繖閲岀殑鍙︿竴涓師鍥犳槸 tryLock() 澶辫触锛屾墍浠ヨ妲藉瓨鍦ㄥ苟鍙戯紝涓嶄竴瀹氭槸璇ヤ綅缃?/code>
                    node = new HashEntry<K,V>(hash, key, value, null);
                retries = 0;
            }
            else if (key.equals(e.key))
                retries = 0;
            else
                // 椤虹潃閾捐〃寰€涓嬭蛋
                e = e.next;
        }
        // 閲嶈瘯娆℃暟濡傛灉瓒呰繃 MAX_SCAN_RETRIES锛堝崟鏍?澶氭牳64锛夛紝閭d箞涓嶆姠浜嗭紝杩涘叆鍒伴樆濉為槦鍒楃瓑寰呴攣
        //    lock() 鏄樆濉炴柟娉曪紝鐩村埌鑾峰彇閿佸悗杩斿洖
        else if (++retries > MAX_SCAN_RETRIES) {
            lock();
            break;
        }
        else if ((retries & 1) == 0 &&
                 // 杩欎釜鏃跺€欐槸鏈夊ぇ闂浜嗭紝閭e氨鏄湁鏂扮殑鍏冪礌杩涘埌浜嗛摼琛紝鎴愪负浜嗘柊鐨勮〃澶?/code>
                 //     鎵€浠ヨ繖杈圭殑绛栫暐鏄紝鐩稿綋浜庨噸鏂拌蛋涓€閬嶈繖涓?scanAndLockForPut 鏂规硶
                 (f = entryForHash(this, hash)) != first) {
            e = first = f; // re-traverse if entry changed
            retries = -1;
        }
    }
    return node;
}

杩欎釜鏂规硶鏈変袱涓嚭鍙o紝涓€涓槸 tryLock() 鎴愬姛浜嗭紝寰幆缁堟锛屽彟涓€涓氨鏄噸璇曟鏁拌秴杩囦簡 MAX_SCAN_RETRIES锛岃繘鍒?lock() 鏂规硶锛屾鏂规硶浼氶樆濉炵瓑寰咃紝鐩村埌鎴愬姛鎷垮埌鐙崰閿併€?/p>

杩欎釜鏂规硶灏辨槸鐪嬩技澶嶆潅锛屼絾鏄叾瀹炲氨鏄仛浜嗕竴浠朵簨锛岄偅灏辨槸鑾峰彇璇?segment 鐨勭嫭鍗犻攣锛屽鏋滈渶瑕佺殑璇濋『渚垮疄渚嬪寲浜嗕竴涓?node銆?/p>

鎵╁: rehash

閲嶅涓€涓嬶紝segment 鏁扮粍涓嶈兘鎵╁锛屾墿瀹规槸 segment 鏁扮粍鏌愪釜浣嶇疆鍐呴儴鐨勬暟缁?HashEntry[] 杩涜鎵╁锛屾墿瀹瑰悗锛屽閲忎负鍘熸潵鐨?2 鍊嶃€?/p>

棣栧厛锛屾垜浠鍥為【涓€涓嬭Е鍙戞墿瀹圭殑鍦版柟锛宲ut 鐨勬椂鍊欙紝濡傛灉鍒ゆ柇璇ュ€肩殑鎻掑叆浼氬鑷磋 segment 鐨勫厓绱犱釜鏁拌秴杩囬槇鍊硷紝閭d箞鍏堣繘琛屾墿瀹癸紝鍐嶆彃鍊硷紝璇昏€呰繖涓椂鍊欏彲浠ュ洖鍘?put 鏂规硶鐪嬩竴鐪笺€?/p>

璇ユ柟娉曚笉闇€瑕佽€冭檻骞跺彂锛屽洜涓哄埌杩欓噷鐨勬椂鍊欙紝鏄寔鏈夎 segment 鐨勭嫭鍗犻攣鐨勩€?/p>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// 鏂规硶鍙傛暟涓婄殑 node 鏄繖娆℃墿瀹瑰悗锛岄渶瑕佹坊鍔犲埌鏂扮殑鏁扮粍涓殑鏁版嵁銆?/code>
private void rehash(HashEntry<K,V> node) {
    HashEntry<K,V>[] oldTable = table;
    int oldCapacity = oldTable.length;
    // 2 鍊?/code>
    int newCapacity = oldCapacity << 1;
    threshold = (int)(newCapacity * loadFactor);
    // 鍒涘缓鏂版暟缁?/code>
    HashEntry<K,V>[] newTable =
        (HashEntry<K,V>[]) new HashEntry[newCapacity];
    // 鏂扮殑鎺╃爜锛屽浠?16 鎵╁鍒?32锛岄偅涔?sizeMask 涓?31锛屽搴斾簩杩涘埗 鈥?00...00011111鈥?/code>
    int sizeMask = newCapacity - 1;
 
    // 閬嶅巻鍘熸暟缁勶紝鑰佸璺紝灏嗗師鏁扮粍浣嶇疆 i 澶勭殑閾捐〃鎷嗗垎鍒?鏂版暟缁勪綅缃?i 鍜?i+oldCap 涓や釜浣嶇疆
    for (int i = 0; i < oldCapacity ; i++) {
        // e 鏄摼琛ㄧ殑绗竴涓厓绱?/code>
        HashEntry<K,V> e = oldTable[i];
        if (e != null) {
            HashEntry<K,V> next = e.next;
            // 璁$畻搴旇鏀剧疆鍦ㄦ柊鏁扮粍涓殑浣嶇疆锛?/code>
            // 鍋囪鍘熸暟缁勯暱搴︿负 16锛宔 鍦?oldTable[3] 澶勶紝閭d箞 idx 鍙彲鑳芥槸 3 鎴栬€呮槸 3 + 16 = 19
            int idx = e.hash & sizeMask;
            if (next == null)   // 璇ヤ綅缃鍙湁涓€涓厓绱狅紝閭f瘮杈冨ソ鍔?/code>
                newTable[idx] = e;
            else { // Reuse consecutive sequence at same slot
                // e 鏄摼琛ㄨ〃澶?/code>
                HashEntry<K,V> lastRun = e;
                // idx 鏄綋鍓嶉摼琛ㄧ殑澶寸粨鐐?e 鐨勬柊浣嶇疆
                int lastIdx = idx;
 
                // 涓嬮潰杩欎釜 for 寰幆浼氭壘鍒颁竴涓?lastRun 鑺傜偣锛岃繖涓妭鐐逛箣鍚庣殑鎵€鏈夊厓绱犳槸灏嗚鏀惧埌涓€璧风殑
                for (HashEntry<K,V> last = next;
                     last != null;
                     last = last.next) {
                    int k = last.hash & sizeMask;
                    if (k != lastIdx) {
                        lastIdx = k;
                        lastRun = last;
                    }
                }
                // 灏?lastRun 鍙婂叾涔嬪悗鐨勬墍鏈夎妭鐐圭粍鎴愮殑杩欎釜閾捐〃鏀惧埌 lastIdx 杩欎釜浣嶇疆
                newTable[lastIdx] = lastRun;
                // 涓嬮潰鐨勬搷浣滄槸澶勭悊 lastRun 涔嬪墠鐨勮妭鐐癸紝
                //    杩欎簺鑺傜偣鍙兘鍒嗛厤鍦ㄥ彟涓€涓摼琛ㄤ腑锛屼篃鍙兘鍒嗛厤鍒颁笂闈㈢殑閭d釜閾捐〃涓?/code>
                for (HashEntry<K,V> p = e; p != lastRun; p = p.next) {
                    V v = p.value;
                    int h = p.hash;
                    int k = h & sizeMask;
                    HashEntry<K,V> n = newTable[k];
                    newTable[k] = new HashEntry<K,V>(h, p.key, v, n);
                }
            }
        }
    }
    // 灏嗘柊鏉ョ殑 node 鏀惧埌鏂版暟缁勪腑鍒氬垰鐨?涓や釜閾捐〃涔嬩竴 鐨?澶撮儴
    int nodeIndex = node.hash & sizeMask; // add the new node
    node.setNext(newTable[nodeIndex]);
    newTable[nodeIndex] = node;
    table = newTable;
}

杩欓噷鐨勬墿瀹规瘮涔嬪墠鐨?HashMap 瑕佸鏉備竴浜涳紝浠g爜闅炬噦涓€鐐广€備笂闈㈡湁涓や釜鎸ㄧ潃鐨?for 寰幆锛岀涓€涓?for 鏈変粈涔堢敤鍛紵

浠旂粏涓€鐪嬪彂鐜帮紝濡傛灉娌℃湁绗竴涓?for 寰幆锛屼篃鏄彲浠ュ伐浣滅殑锛屼絾鏄紝杩欎釜 for 寰幆涓嬫潵锛屽鏋?lastRun 鐨勫悗闈㈣繕鏈夋瘮杈冨鐨勮妭鐐癸紝閭d箞杩欐灏辨槸鍊煎緱鐨勩€傚洜涓烘垜浠彧闇€瑕佸厠闅?lastRun 鍓嶉潰鐨勮妭鐐癸紝鍚庨潰鐨勪竴涓茶妭鐐硅窡鐫€ lastRun 璧板氨鏄簡锛屼笉闇€瑕佸仛浠讳綍鎿嶄綔銆?/p>

鎴戣寰?Doug Lea 鐨勮繖涓兂娉曚篃鏄尯鏈夋剰鎬濈殑锛屼笉杩囨瘮杈冨潖鐨勬儏鍐靛氨鏄瘡娆?lastRun 閮芥槸閾捐〃鐨勬渶鍚庝竴涓厓绱犳垨鑰呭緢闈犲悗鐨勫厓绱狅紝閭d箞杩欐閬嶅巻灏辨湁鐐规氮璐逛簡銆備笉杩?Doug Lea 涔熻浜嗭紝鏍规嵁缁熻锛屽鏋滀娇鐢ㄩ粯璁ょ殑闃堝€硷紝澶х害鍙湁 1/6 鐨勮妭鐐归渶瑕佸厠闅嗐€?/p>

get 杩囩▼鍒嗘瀽

鐩稿浜?put 鏉ヨ锛実et 鐪熺殑涓嶈澶畝鍗曘€?/p>

  1. 璁$畻 hash 鍊硷紝鎵惧埌 segment 鏁扮粍涓殑鍏蜂綋浣嶇疆锛屾垨鎴戜滑鍓嶉潰鐢ㄧ殑鈥滄Ы鈥?/li>
  2. 妲戒腑涔熸槸涓€涓暟缁勶紝鏍规嵁 hash 鎵惧埌鏁扮粍涓叿浣撶殑浣嶇疆
  3. 鍒拌繖閲屾槸閾捐〃浜嗭紝椤虹潃閾捐〃杩涜鏌ユ壘鍗冲彲
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public V get(Object key) {
    Segment<K,V> s; // manually integrate access methods to reduce overhead
    HashEntry<K,V>[] tab;
    // 1. hash 鍊?/code>
    int h = hash(key);
    long u = (((h >>> segmentShift) & segmentMask) << SSHIFT) + SBASE;
    // 2. 鏍规嵁 hash 鎵惧埌瀵瑰簲鐨?segment
    if ((s = (Segment<K,V>)UNSAFE.getObjectVolatile(segments, u)) != null &&
        (tab = s.table) != null) {
        // 3. 鎵惧埌segment 鍐呴儴鏁扮粍鐩稿簲浣嶇疆鐨勯摼琛紝閬嶅巻
        for (HashEntry<K,V> e = (HashEntry<K,V>) UNSAFE.getObjectVolatile
                 (tab, ((long)(((tab.length - 1) & h)) << TSHIFT) + TBASE);
             e != null; e = e.next) {
            K k;
            if ((k = e.key) == key || (e.hash == h && key.equals(k)))
                return e.value;
        }
    }
    return null;
}

骞跺彂闂鍒嗘瀽

鐜板湪鎴戜滑宸茬粡璇村畬浜?put 杩囩▼鍜?get 杩囩▼锛屾垜浠彲浠ョ湅鍒?get 杩囩▼涓槸娌℃湁鍔犻攣鐨勶紝閭h嚜鐒舵垜浠氨闇€瑕佸幓鑰冭檻骞跺彂闂銆?/p>

娣诲姞鑺傜偣鐨勬搷浣?put 鍜屽垹闄よ妭鐐圭殑鎿嶄綔 remove 閮芥槸瑕佸姞 segment 涓婄殑鐙崰閿佺殑锛屾墍浠ュ畠浠箣闂磋嚜鐒朵笉浼氭湁闂锛屾垜浠渶瑕佽€冭檻鐨勯棶棰樺氨鏄?get 鐨勬椂鍊欏湪鍚屼竴涓?segment 涓彂鐢熶簡 put 鎴?remove 鎿嶄綔銆?/p>

  1. put 鎿嶄綔鐨勭嚎绋嬪畨鍏ㄦ€с€?
    • 鍒濆鍖栨Ы锛岃繖涓垜浠箣鍓嶅氨璇磋繃浜嗭紝浣跨敤浜?CAS 鏉ュ垵濮嬪寲 Segment 涓殑鏁扮粍銆?/li>
    • 娣诲姞鑺傜偣鍒伴摼琛ㄧ殑鎿嶄綔鏄彃鍏ュ埌琛ㄥご鐨勶紝鎵€浠ワ紝濡傛灉杩欎釜鏃跺€?get 鎿嶄綔鍦ㄩ摼琛ㄩ亶鍘嗙殑杩囩▼宸茬粡鍒颁簡涓棿锛屾槸涓嶄細褰卞搷鐨勩€傚綋鐒讹紝鍙︿竴涓苟鍙戦棶棰樺氨鏄?get 鎿嶄綔鍦?put 涔嬪悗锛岄渶瑕佷繚璇佸垰鍒氭彃鍏ヨ〃澶寸殑鑺傜偣琚鍙栵紝杩欎釜渚濊禆浜?setEntryAt 鏂规硶涓娇鐢ㄧ殑 UNSAFE.putOrderedObject銆?/li>
    • 鎵╁銆傛墿瀹规槸鏂板垱寤轰簡鏁扮粍锛岀劧鍚庤繘琛岃縼绉绘暟鎹紝鏈€鍚庨潰灏?newTable 璁剧疆缁欏睘鎬?table銆傛墍浠ワ紝濡傛灉 get 鎿嶄綔姝ゆ椂涔熷湪杩涜锛岄偅涔堜篃娌″叧绯伙紝濡傛灉 get 鍏堣锛岄偅涔堝氨鏄湪鏃х殑 table 涓婂仛鏌ヨ鎿嶄綔锛涜€?put 鍏堣锛岄偅涔?put 鎿嶄綔鐨勫彲瑙佹€т繚璇佸氨鏄?table 浣跨敤浜?volatile 鍏抽敭瀛椼€?/li>
  2. remove 鎿嶄綔鐨勭嚎绋嬪畨鍏ㄦ€с€?

    remove 鎿嶄綔鎴戜滑娌℃湁鍒嗘瀽婧愮爜锛屾墍浠ヨ繖閲岃鐨勮鑰呮劅鍏磋叮鐨勮瘽杩樻槸闇€瑕佸埌婧愮爜涓幓姹傚疄涓€涓嬬殑銆?/p>

    get 鎿嶄綔闇€瑕侀亶鍘嗛摼琛紝浣嗘槸 remove 鎿嶄綔浼氣€濈牬鍧忊€濋摼琛ㄣ€?/p>

    濡傛灉 remove 鐮村潖鐨勮妭鐐?get 鎿嶄綔宸茬粡杩囧幓浜嗭紝閭d箞杩欓噷涓嶅瓨鍦ㄤ换浣曢棶棰樸€?/p>

    濡傛灉 remove 鍏堢牬鍧忎簡涓€涓妭鐐癸紝鍒嗕袱绉嶆儏鍐佃€冭檻銆?1銆佸鏋滄鑺傜偣鏄ご缁撶偣锛岄偅涔堥渶瑕佸皢澶寸粨鐐圭殑 next 璁剧疆涓烘暟缁勮浣嶇疆鐨勫厓绱狅紝table 铏界劧浣跨敤浜?volatile 淇グ锛屼絾鏄?volatile 骞朵笉鑳芥彁渚涙暟缁勫唴閮ㄦ搷浣滅殑鍙鎬т繚璇侊紝鎵€浠ユ簮鐮佷腑浣跨敤浜?UNSAFE 鏉ユ搷浣滄暟缁勶紝璇风湅鏂规硶 setEntryAt銆?銆佸鏋滆鍒犻櫎鐨勮妭鐐逛笉鏄ご缁撶偣锛屽畠浼氬皢瑕佸垹闄よ妭鐐圭殑鍚庣户鑺傜偣鎺ュ埌鍓嶉┍鑺傜偣涓紝杩欓噷鐨勫苟鍙戜繚璇佸氨鏄?next 灞炴€ф槸 volatile 鐨勩€?/p>

Java8 HashMap

Java8 瀵?HashMap 杩涜浜嗕竴浜涗慨鏀癸紝鏈€澶х殑涓嶅悓灏辨槸鍒╃敤浜嗙孩榛戞爲锛屾墍浠ュ叾鐢?nbsp;鏁扮粍+閾捐〃+绾㈤粦鏍?nbsp;缁勬垚銆?/p>

鏍规嵁 Java7 HashMap 鐨勪粙缁嶏紝鎴戜滑鐭ラ亾锛屾煡鎵剧殑鏃跺€欙紝鏍规嵁 hash 鍊兼垜浠兘澶熷揩閫熷畾浣嶅埌鏁扮粍鐨勫叿浣撲笅鏍囷紝浣嗘槸涔嬪悗鐨勮瘽锛岄渶瑕侀『鐫€閾捐〃涓€涓釜姣旇緝涓嬪幓鎵嶈兘鎵惧埌鎴戜滑闇€瑕佺殑锛屾椂闂村鏉傚害鍙栧喅浜庨摼琛ㄧ殑闀垮害锛屼负 O(n)銆?/p>

涓轰簡闄嶄綆杩欓儴鍒嗙殑寮€閿€锛屽湪 Java8 涓紝褰撻摼琛ㄤ腑鐨勫厓绱犺秴杩囦簡 8 涓互鍚庯紝浼氬皢閾捐〃杞崲涓虹孩榛戞爲锛屽湪杩欎簺浣嶇疆杩涜鏌ユ壘鐨勬椂鍊欏彲浠ラ檷浣庢椂闂村鏉傚害涓?nbsp;O(logN)銆?/p>

鏉ヤ竴寮犲浘绠€鍗曠ず鎰忎竴涓嬪惂锛?/p>

鎶€鏈垎浜浘鐗? src=

娉ㄦ剰锛屼笂鍥炬槸绀烘剰鍥撅紝涓昏鏄弿杩扮粨鏋勶紝涓嶄細杈惧埌杩欎釜鐘舵€佺殑锛屽洜涓鸿繖涔堝鏁版嵁鐨勬椂鍊欐棭灏辨墿瀹逛簡銆?/p>

涓嬮潰锛屾垜浠繕鏄敤浠g爜鏉ヤ粙缁嶅惂锛屼釜浜烘劅瑙夛紝Java8 鐨勬簮鐮佸彲璇绘€ц宸竴浜涳紝涓嶈繃绮剧畝涓€浜涖€?/p>

Java7 涓娇鐢?Entry 鏉ヤ唬琛ㄦ瘡涓?HashMap 涓殑鏁版嵁鑺傜偣锛孞ava8 涓娇鐢?nbsp;Node锛屽熀鏈病鏈夊尯鍒紝閮芥槸 key锛寁alue锛宧ash 鍜?next 杩欏洓涓睘鎬э紝涓嶈繃锛孨ode 鍙兘鐢ㄤ簬閾捐〃鐨勬儏鍐碉紝绾㈤粦鏍戠殑鎯呭喌闇€瑕佷娇鐢?nbsp;TreeNode銆?/p>

鎴戜滑鏍规嵁鏁扮粍鍏冪礌涓紝绗竴涓妭鐐规暟鎹被鍨嬫槸 Node 杩樻槸 TreeNode 鏉ュ垽鏂浣嶇疆涓嬫槸閾捐〃杩樻槸绾㈤粦鏍戠殑銆?/p>

put 杩囩▼鍒嗘瀽

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}
 
// 绗笁涓弬鏁?onlyIfAbsent 濡傛灉鏄?true锛岄偅涔堝彧鏈夊湪涓嶅瓨鍦ㄨ key 鏃舵墠浼氳繘琛?put 鎿嶄綔
// 绗洓涓弬鏁?evict 鎴戜滑杩欓噷涓嶅叧蹇?/code>
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
               boolean evict) {
    Node<K,V>[] tab; Node<K,V> p; int n, i;
    // 绗竴娆?put 鍊肩殑鏃跺€欙紝浼氳Е鍙戜笅闈㈢殑 resize()锛岀被浼?java7 鐨勭涓€娆?put 涔熻鍒濆鍖栨暟缁勯暱搴?/code>
    // 绗竴娆?resize 鍜屽悗缁殑鎵╁鏈変簺涓嶄竴鏍凤紝鍥犱负杩欐鏄暟缁勪粠 null 鍒濆鍖栧埌榛樿鐨?16 鎴栬嚜瀹氫箟鐨勫垵濮嬪閲?/code>
    if ((tab = table) == null || (n = tab.length) == 0)
        n = (tab = resize()).length;
    // 鎵惧埌鍏蜂綋鐨勬暟缁勪笅鏍囷紝濡傛灉姝や綅缃病鏈夊€硷紝閭d箞鐩存帴鍒濆鍖栦竴涓?Node 骞舵斁缃湪杩欎釜浣嶇疆灏卞彲浠ヤ簡
    if ((p = tab[i = (n - 1) & hash]) == null)
        tab[i] = newNode(hash, key, value, null);
 
    else {// 鏁扮粍璇ヤ綅缃湁鏁版嵁
        Node<K,V> e; K k;
        // 棣栧厛锛屽垽鏂浣嶇疆鐨勭涓€涓暟鎹拰鎴戜滑瑕佹彃鍏ョ殑鏁版嵁锛宬ey 鏄笉鏄?鐩哥瓑"锛屽鏋滄槸锛屽彇鍑鸿繖涓妭鐐?/code>
        if (p.hash == hash &&
            ((k = p.key) == key || (key != null && key.equals(k))))
            e = p;
        // 濡傛灉璇ヨ妭鐐规槸浠h〃绾㈤粦鏍戠殑鑺傜偣锛岃皟鐢ㄧ孩榛戞爲鐨勬彃鍊兼柟娉曪紝鏈枃涓嶅睍寮€璇寸孩榛戞爲
        else if (p instanceof TreeNode)
            e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
        else {
            // 鍒拌繖閲岋紝璇存槑鏁扮粍璇ヤ綅缃笂鏄竴涓摼琛?/code>
            for (int binCount = 0; ; ++binCount) {
                // 鎻掑叆鍒伴摼琛ㄧ殑鏈€鍚庨潰(Java7 鏄彃鍏ュ埌閾捐〃鐨勬渶鍓嶉潰)
                if ((e = p.next) == null) {
                    p.next = newNode(hash, key, value, null);
                    // TREEIFY_THRESHOLD 涓?8锛屾墍浠ワ紝濡傛灉鏂版彃鍏ョ殑鍊兼槸閾捐〃涓殑绗?9 涓?/code>
                    // 浼氳Е鍙戜笅闈㈢殑 treeifyBin锛屼篃灏辨槸灏嗛摼琛ㄨ浆鎹负绾㈤粦鏍?/code>
                    if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                        treeifyBin(tab, hash);
                    break;
                }
                // 濡傛灉鍦ㄨ閾捐〃涓壘鍒颁簡"鐩哥瓑"鐨?key(== 鎴?equals)
                if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k))))
                    // 姝ゆ椂 break锛岄偅涔?e 涓洪摼琛ㄤ腑[涓庤鎻掑叆鐨勬柊鍊肩殑 key "鐩哥瓑"]鐨?node
                    break;
                p = e;
            }
        }
        // e!=null 璇存槑瀛樺湪鏃у€肩殑key涓庤鎻掑叆鐨刱ey"鐩哥瓑"
        // 瀵逛簬鎴戜滑鍒嗘瀽鐨刾ut鎿嶄綔锛屼笅闈㈣繖涓?if 鍏跺疄灏辨槸杩涜 "鍊艰鐩?锛岀劧鍚庤繑鍥炴棫鍊?/code>
        if (e != null) {
            V oldValue = e.value;
            if (!onlyIfAbsent || oldValue == null)
                e.value = value;
            afterNodeAccess(e);
            return oldValue;
        }
    }
    ++modCount;
    // 濡傛灉 HashMap 鐢变簬鏂版彃鍏ヨ繖涓€煎鑷?size 宸茬粡瓒呰繃浜嗛槇鍊硷紝闇€瑕佽繘琛屾墿瀹?/code>
    if (++size > threshold)
        resize();
    afterNodeInsertion(evict);
    return null;
}

鍜?Java7 绋嶅井鏈夌偣涓嶄竴鏍风殑鍦版柟灏辨槸锛孞ava7 鏄厛鎵╁鍚庢彃鍏ユ柊鍊肩殑锛孞ava8 鍏堟彃鍊煎啀鎵╁锛屼笉杩囪繖涓笉閲嶈銆?/p>

鏁扮粍鎵╁

resize() 鏂规硶鐢ㄤ簬鍒濆鍖栨暟缁勬垨鏁扮粍鎵╁锛屾瘡娆℃墿瀹瑰悗锛屽閲忎负鍘熸潵鐨?2 鍊嶏紝骞惰繘琛屾暟鎹縼绉?/span>銆?/p>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
final Node<K,V>[] resize() {
    Node<K,V>[] oldTab = table;
    int oldCap = (oldTab == null) ? 0 : oldTab.length;
    int oldThr = threshold;
    int newCap, newThr = 0;
    if (oldCap > 0) { // 瀵瑰簲鏁扮粍鎵╁
        if (oldCap >= MAXIMUM_CAPACITY) {
            threshold = Integer.MAX_VALUE;
            return oldTab;
        }
        // 灏嗘暟缁勫ぇ灏忔墿澶т竴鍊?/code>
        else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
                 oldCap >= DEFAULT_INITIAL_CAPACITY)
            // 灏嗛槇鍊兼墿澶т竴鍊?/code>
            newThr = oldThr << 1; // double threshold
    }
    else if (oldThr > 0) // 瀵瑰簲浣跨敤 new HashMap(int initialCapacity) 鍒濆鍖栧悗锛岀涓€娆?put 鐨勬椂鍊?/code>
        newCap = oldThr;
    else {// 瀵瑰簲浣跨敤 new HashMap() 鍒濆鍖栧悗锛岀涓€娆?put 鐨勬椂鍊?/code>
        newCap = DEFAULT_INITIAL_CAPACITY;
        newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
    }
 
    if (newThr == 0) {
        float ft = (float)newCap * loadFactor;
        newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
                  (int)ft : Integer.MAX_VALUE);
    }
    threshold = newThr;
 
    // 鐢ㄦ柊鐨勬暟缁勫ぇ灏忓垵濮嬪寲鏂扮殑鏁扮粍
    Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
    table = newTab; // 濡傛灉鏄垵濮嬪寲鏁扮粍锛屽埌杩欓噷灏辩粨鏉熶簡锛岃繑鍥?newTab 鍗冲彲
 
    if (oldTab != null) {
        // 寮€濮嬮亶鍘嗗師鏁扮粍锛岃繘琛屾暟鎹縼绉汇€?/code>
        for (int j = 0; j < oldCap; ++j) {
            Node<K,V> e;
            if ((e = oldTab[j]) != null) {
                oldTab[j] = null;
                // 濡傛灉璇ユ暟缁勪綅缃笂鍙湁鍗曚釜鍏冪礌锛岄偅灏辩畝鍗曚簡锛岀畝鍗曡縼绉昏繖涓厓绱犲氨鍙互浜?/code>
                if (e.next == null)
                    newTab[e.hash & (newCap - 1)] = e;
                // 濡傛灉鏄孩榛戞爲锛屽叿浣撴垜浠氨涓嶅睍寮€浜?/code>
                else if (e instanceof TreeNode)
                    ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
                else {
                    // 杩欏潡鏄鐞嗛摼琛ㄧ殑鎯呭喌锛?/code>
                    // 闇€瑕佸皢姝ら摼琛ㄦ媶鎴愪袱涓摼琛紝鏀惧埌鏂扮殑鏁扮粍涓紝骞朵笖淇濈暀鍘熸潵鐨勫厛鍚庨『搴?/code>
                    // loHead銆乴oTail 瀵瑰簲涓€鏉¢摼琛紝hiHead銆乭iTail 瀵瑰簲鍙︿竴鏉¢摼琛紝浠g爜杩樻槸姣旇緝绠€鍗曠殑
                    Node<K,V> loHead = null, loTail = null;
                    Node<K,V> hiHead = null, hiTail = null;
                    Node<K,V> next;
                    do {
                        next = e.next;
                        if ((e.hash & oldCap) == 0) {
                            if (loTail == null)
                                loHead = e;
                            else
                                loTail.next = e;
                            loTail = e;
                        }
                        else {
                            if (hiTail == null)
                                hiHead = e;
                            else
                                hiTail.next = e;
                            hiTail = e;
                        }
                    } while ((e = next) != null);
                    if (loTail != null) {
                        loTail.next = null;
                        // 绗竴鏉¢摼琛?/code>
                        newTab[j] = loHead;
                    }
                    if (hiTail != null) {
                        hiTail.next = null;
                        // 绗簩鏉¢摼琛ㄧ殑鏂扮殑浣嶇疆鏄?j + oldCap锛岃繖涓緢濂界悊瑙?/code>
                        newTab[j + oldCap] = hiHead;
                    }
                }
            }
        }
    }
    return newTab;
}

get 杩囩▼鍒嗘瀽

鐩稿浜?put 鏉ヨ锛実et 鐪熺殑澶畝鍗曚簡銆?/p>

  1. 璁$畻 key 鐨?hash 鍊硷紝鏍规嵁 hash 鍊兼壘鍒板搴旀暟缁勪笅鏍? hash & (length-1)
  2. 鍒ゆ柇鏁扮粍璇ヤ綅缃鐨勫厓绱犳槸鍚﹀垰濂藉氨鏄垜浠鎵剧殑锛屽鏋滀笉鏄紝璧扮涓夋
  3. 鍒ゆ柇璇ュ厓绱犵被鍨嬫槸鍚︽槸 TreeNode锛屽鏋滄槸锛岀敤绾㈤粦鏍戠殑鏂规硶鍙栨暟鎹紝濡傛灉涓嶆槸锛岃蛋绗洓姝?/li>
  4. 閬嶅巻閾捐〃锛岀洿鍒版壘鍒扮浉绛?==鎴杄quals)鐨?key
1
2
3
4
public V get(Object key) {
    Node<K,V> e;
    return (e = getNode(hash(key), key)) == null ? null : e.value;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
final Node<K,V> getNode(int hash, Object key) {
    Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
    if ((tab = table) != null && (n = tab.length) > 0 &&
        (first = tab[(n - 1) & hash]) != null) {
        // 鍒ゆ柇绗竴涓妭鐐规槸涓嶆槸灏辨槸闇€瑕佺殑
        if (first.hash == hash && // always check first node
            ((k = first.key) == key || (key != null && key.equals(k))))
            return first;
        if ((e = first.next) != null) {
            // 鍒ゆ柇鏄惁鏄孩榛戞爲
            if (first instanceof TreeNode)
                return ((TreeNode<K,V>)first).getTreeNode(hash, key);
 
            // 閾捐〃閬嶅巻
            do {
                if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k))))
                    return e;
            } while ((e = e.next) != null);
        }
    }
    return null;
}

Java8 ConcurrentHashMap

Java7 涓疄鐜扮殑 ConcurrentHashMap 璇村疄璇濊繕鏄瘮杈冨鏉傜殑锛孞ava8 瀵?ConcurrentHashMap 杩涜浜嗘瘮杈冨ぇ鐨勬敼鍔ㄣ€傚缓璁鑰呭彲浠ュ弬鑰?Java8 涓?HashMap 鐩稿浜?Java7 HashMap 鐨勬敼鍔紝瀵逛簬 ConcurrentHashMap锛孞ava8 涔熷紩鍏ヤ簡绾㈤粦鏍戙€?/p>

璇村疄璇濓紝Java8 ConcurrentHashMap 婧愮爜鐪熷績涓嶇畝鍗曪紝鏈€闅剧殑鍦ㄤ簬鎵╁锛屾暟鎹縼绉绘搷浣滀笉瀹规槗鐪嬫噦銆?/p>

鎴戜滑鍏堢敤涓€涓ず鎰忓浘鏉ユ弿杩颁笅鍏剁粨鏋勶細

鎶€鏈垎浜浘鐗? src=

缁撴瀯涓婂拰 Java8 鐨?HashMap 鍩烘湰涓婁竴鏍凤紝涓嶈繃瀹冭淇濊瘉绾跨▼瀹夊叏鎬?/span>锛屾墍浠ュ湪婧愮爜涓婄‘瀹炶澶嶆潅涓€浜涖€?/p>

鍒濆鍖?/h3>
1
2
3
4
5
6
7
8
9
10
11
// 杩欐瀯閫犲嚱鏁伴噷锛屼粈涔堥兘涓嶅共
public ConcurrentHashMap() {
}
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;
}

杩欎釜鍒濆鍖栨柟娉曟湁鐐规剰鎬濓紝閫氳繃鎻愪緵鍒濆瀹归噺锛岃绠椾簡 sizeCtl锛宻izeCtl = 銆?(1.5 * initialCapacity + 1)锛岀劧鍚庡悜涓婂彇鏈€杩戠殑 2 鐨?n 娆℃柟銆戙€傚 initialCapacity 涓?10锛岄偅涔堝緱鍒?sizeCtl 涓?16锛屽鏋?initialCapacity 涓?11锛屽緱鍒?sizeCtl 涓?32銆?/p>

sizeCtl 杩欎釜灞炴€т娇鐢ㄧ殑鍦烘櫙寰堝锛屼笉杩囧彧瑕佽窡鐫€鏂囩珷鐨勬€濊矾鏉ワ紝灏变笉浼氳瀹冩悶鏅曚簡銆?/p>

濡傛灉浣犵埍鎶樿吘锛屼篃鍙互鐪嬩笅鍙︿竴涓湁涓変釜鍙傛暟鐨勬瀯閫犳柟娉曪紝杩欓噷鎴戝氨涓嶈浜嗭紝澶ч儴鍒嗘椂鍊欙紝鎴戜滑浼氫娇鐢ㄦ棤鍙傛瀯閫犲嚱鏁拌繘琛屽疄渚嬪寲锛屾垜浠篃鎸夌収杩欎釜鎬濊矾鏉ヨ繘琛屾簮鐮佸垎鏋愬惂銆?/p>

put 杩囩▼鍒嗘瀽

浠旂粏鍦颁竴琛屼竴琛屼唬鐮佺湅涓嬪幓锛?/p>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
public V put(K key, V value) {
    return putVal(key, value, false);
}
final V putVal(K key, V value, boolean onlyIfAbsent) {
    if (key == null || value == null) throw new NullPointerException();
    // 寰楀埌 hash 鍊?/code>
    int hash = spread(key.hashCode());
    // 鐢ㄤ簬璁板綍鐩稿簲閾捐〃鐨勯暱搴?/code>
    int binCount = 0;
    for (Node<K,V>[] tab = table;;) {
        Node<K,V> f; int n, i, fh;
        // 濡傛灉鏁扮粍"绌?锛岃繘琛屾暟缁勫垵濮嬪寲
        if (tab == null || (n = tab.length) == 0)
            // 鍒濆鍖栨暟缁勶紝鍚庨潰浼氳缁嗕粙缁?/code>
            tab = initTable();
 
        // 鎵捐 hash 鍊煎搴旂殑鏁扮粍涓嬫爣锛屽緱鍒扮涓€涓妭鐐?f
        else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
            // 濡傛灉鏁扮粍璇ヤ綅缃负绌猴紝
            //    鐢ㄤ竴娆?CAS 鎿嶄綔灏嗚繖涓柊鍊兼斁鍏ュ叾涓嵆鍙紝杩欎釜 put 鎿嶄綔宸笉澶氬氨缁撴潫浜嗭紝鍙互鎷夊埌鏈€鍚庨潰浜?/code>
            //          濡傛灉 CAS 澶辫触锛岄偅灏辨槸鏈夊苟鍙戞搷浣滐紝杩涘埌涓嬩竴涓惊鐜氨濂戒簡
            if (casTabAt(tab, i, null,
                         new Node<K,V>(hash, key, value, null)))
                break;                   // no lock when adding to empty bin
        }
        // hash 灞呯劧鍙互绛変簬 MOVED锛岃繖涓渶瑕佸埌鍚庨潰鎵嶈兘鐪嬫槑鐧斤紝涓嶈繃浠庡悕瀛椾笂涔熻兘鐚滃埌锛岃偗瀹氭槸鍥犱负鍦ㄦ墿瀹?/code>
        else if ((fh = f.hash) == MOVED)
            // 甯姪鏁版嵁杩佺Щ锛岃繖涓瓑鍒扮湅瀹屾暟鎹縼绉婚儴鍒嗙殑浠嬬粛鍚庯紝鍐嶇悊瑙h繖涓氨寰堢畝鍗曚簡
            tab = helpTransfer(tab, f);
 
        else { // 鍒拌繖閲屽氨鏄锛宖 鏄浣嶇疆鐨勫ご缁撶偣锛岃€屼笖涓嶄负绌?/code>
 
            V oldVal = null;
            // 鑾峰彇鏁扮粍璇ヤ綅缃殑澶寸粨鐐圭殑鐩戣鍣ㄩ攣
            synchronized (f) {
                if (tabAt(tab, i) == f) {
                    if (fh >= 0) { // 澶寸粨鐐圭殑 hash 鍊煎ぇ浜?0锛岃鏄庢槸閾捐〃
                        // 鐢ㄤ簬绱姞锛岃褰曢摼琛ㄧ殑闀垮害
                        binCount = 1;
                        // 閬嶅巻閾捐〃
                        for (Node<K,V> e = f;; ++binCount) {
                            K ek;
                            // 濡傛灉鍙戠幇浜?鐩哥瓑"鐨?key锛屽垽鏂槸鍚﹁杩涜鍊艰鐩栵紝鐒跺悗涔熷氨鍙互 break 浜?/code>
                            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) { // 绾㈤粦鏍?/code>
                        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;
                        }
                    }
                }
            }
            // binCount != 0 璇存槑涓婇潰鍦ㄥ仛閾捐〃鎿嶄綔
            if (binCount != 0) {
                // 鍒ゆ柇鏄惁瑕佸皢閾捐〃杞崲涓虹孩榛戞爲锛屼复鐣屽€煎拰 HashMap 涓€鏍凤紝涔熸槸 8
                if (binCount >= TREEIFY_THRESHOLD)
                    // 杩欎釜鏂规硶鍜?HashMap 涓◢寰湁涓€鐐圭偣涓嶅悓锛岄偅灏辨槸瀹冧笉鏄竴瀹氫細杩涜绾㈤粦鏍戣浆鎹紝
                    // 濡傛灉褰撳墠鏁扮粍鐨勯暱搴﹀皬浜?64锛岄偅涔堜細閫夋嫨杩涜鏁扮粍鎵╁锛岃€屼笉鏄浆鎹负绾㈤粦鏍?/code>
                    //    鍏蜂綋婧愮爜鎴戜滑灏变笉鐪嬩簡锛屾墿瀹归儴鍒嗗悗闈㈣
                    treeifyBin(tab, i);
                if (oldVal != null)
                    return oldVal;
                break;
            }
        }
    }
    //
    addCount(1L, binCount);
    return null;
}

put 鐨勪富娴佺▼鐪嬪畬浜嗭紝浣嗘槸鑷冲皯鐣欎笅浜嗗嚑涓棶棰橈紝绗竴涓槸鍒濆鍖栵紝绗簩涓槸鎵╁锛岀涓変釜鏄府鍔╂暟鎹縼绉?/span>锛岃繖浜涙垜浠兘浼氬湪鍚庨潰杩涜涓€涓€浠嬬粛銆?/p>

鍒濆鍖栨暟缁勶細initTable

杩欎釜姣旇緝绠€鍗曪紝涓昏灏辨槸鍒濆鍖栦竴涓悎閫傚ぇ灏忕殑鏁扮粍锛岀劧鍚庝細璁剧疆 sizeCtl銆?/p>

鍒濆鍖栨柟娉曚腑鐨勫苟鍙戦棶棰樻槸閫氳繃瀵?sizeCtl 杩涜涓€涓?CAS 鎿嶄綔鏉ユ帶鍒剁殑銆?/p>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private final Node<K,V>[] initTable() {
    Node<K,V>[] tab; int sc;
    while ((tab = table) == null || tab.length == 0) {
        // 鍒濆鍖栫殑"鍔熷姵"琚叾浠栫嚎绋?鎶㈠幓"浜?/code>
        if ((sc = sizeCtl) < 0)
            Thread.yield(); // lost initialization race; just spin
        // CAS 涓€涓嬶紝灏?sizeCtl 璁剧疆涓?-1锛屼唬琛ㄦ姠鍒颁簡閿?/code>
        else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {
            try {
                if ((tab = table) == null || tab.length == 0) {
                    // DEFAULT_CAPACITY 榛樿鍒濆瀹归噺鏄?16
                    int n = (sc > 0) ? sc : DEFAULT_CAPACITY;
                    // 鍒濆鍖栨暟缁勶紝闀垮害涓?16 鎴栧垵濮嬪寲鏃舵彁渚涚殑闀垮害
                    Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];
                    // 灏嗚繖涓暟缁勮祴鍊肩粰 table锛宼able 鏄?volatile 鐨?/code>
                    table = tab = nt;
                    // 濡傛灉 n 涓?16 鐨勮瘽锛岄偅涔堣繖閲?sc = 12
                    // 鍏跺疄灏辨槸 0.75 * n
                    sc = n - (n >>> 2);
                }
            } finally {
                // 璁剧疆 sizeCtl 涓?sc锛屾垜浠氨褰撴槸 12 鍚?/code>
                sizeCtl = sc;
            }
            break;
        }
    }
    return tab;
}

閾捐〃杞孩榛戞爲: treeifyBin

鍓嶉潰鎴戜滑鍦?put 婧愮爜鍒嗘瀽涔熻杩囷紝treeifyBin 涓嶄竴瀹氬氨浼氳繘琛岀孩榛戞爲杞崲锛屼篃鍙兘鏄粎浠呭仛鏁扮粍鎵╁銆傛垜浠繕鏄繘琛屾簮鐮佸垎鏋愬惂銆?/p>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
private final void treeifyBin(Node<K,V>[] tab, int index) {
    Node<K,V> b; int n, sc;
    if (tab != null) {
        // MIN_TREEIFY_CAPACITY 涓?64
        // 鎵€浠ワ紝濡傛灉鏁扮粍闀垮害灏忎簬 64 鐨勬椂鍊欙紝鍏跺疄涔熷氨鏄?32 鎴栬€?16 鎴栬€呮洿灏忕殑鏃跺€欙紝浼氳繘琛屾暟缁勬墿瀹?/code>
        if ((n = tab.length) < MIN_TREEIFY_CAPACITY)
            // 鍚庨潰鎴戜滑鍐嶈缁嗗垎鏋愯繖涓柟娉?/code>
            tryPresize(n << 1);
        // b 鏄ご缁撶偣
        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));
                }
            }
        }
    }
}

鎵╁锛歵ryPresize

濡傛灉璇?Java8 ConcurrentHashMap 鐨勬簮鐮佷笉绠€鍗曪紝閭d箞璇寸殑灏辨槸鎵╁鎿嶄綔鍜岃縼绉绘搷浣溿€?/p>

杩欎釜鏂规硶瑕佸畬瀹屽叏鍏ㄧ湅鎳傝繕闇€瑕佺湅涔嬪悗鐨?transfer 鏂规硶锛岃鑰呭簲璇ユ彁鍓嶇煡閬撹繖鐐广€?/p>

杩欓噷鐨勬墿瀹逛篃鏄仛缈诲€嶆墿瀹圭殑锛屾墿瀹瑰悗鏁扮粍瀹归噺涓哄師鏉ョ殑 2 鍊嶃€?/p>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// 棣栧厛瑕佽鏄庣殑鏄紝鏂规硶鍙傛暟 size 浼犺繘鏉ョ殑鏃跺€欏氨宸茬粡缈讳簡鍊嶄簡
private final void tryPresize(int size) {
    // c锛歴ize 鐨?1.5 鍊嶏紝鍐嶅姞 1锛屽啀寰€涓婂彇鏈€杩戠殑 2 鐨?n 娆℃柟銆?/code>
    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 鍒嗘敮鍜屼箣鍓嶈鐨勫垵濮嬪寲鏁扮粍鐨勪唬鐮佸熀鏈笂鏄竴鏍风殑锛屽湪杩欓噷锛屾垜浠彲浠ヤ笉鐢ㄧ杩欏潡浠g爜
        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); // 0.75 * n
                    }
                } finally {
                    sizeCtl = sc;
                }
            }
        }
        else if (c <= sc || n >= MAXIMUM_CAPACITY)
            break;
        else if (tab == table) {
            // 鎴戞病鐪嬫噦 rs 鐨勭湡姝e惈涔夋槸浠€涔堬紝涓嶈繃涔熷叧绯讳笉澶?/code>
            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;
                // 2. 鐢?CAS 灏?sizeCtl 鍔?1锛岀劧鍚庢墽琛?transfer 鏂规硶
                //    姝ゆ椂 nextTab 涓嶄负 null
                if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1))
                    transfer(tab, nt);
            }
            // 1. 灏?sizeCtl 璁剧疆涓?(rs << RESIZE_STAMP_SHIFT) + 2)
            //     鎴戞槸娌$湅鎳傝繖涓€肩湡姝g殑鎰忎箟鏄粈涔堬紵涓嶈繃鍙互璁$畻鍑烘潵鐨勬槸锛岀粨鏋滄槸涓€涓瘮杈冨ぇ鐨勮礋鏁?/code>
            //  璋冪敤 transfer 鏂规硶锛屾鏃?nextTab 鍙傛暟涓?null
            else if (U.compareAndSwapInt(this, SIZECTL, sc,
                                         (rs << RESIZE_STAMP_SHIFT) + 2))
                transfer(tab, null);
        }
    }
}

杩欎釜鏂规硶鐨勬牳蹇冨湪浜?sizeCtl 鍊肩殑鎿嶄綔锛岄鍏堝皢鍏惰缃负涓€涓礋鏁帮紝鐒跺悗鎵ц transfer(tab, null)锛屽啀涓嬩竴涓惊鐜皢 sizeCtl 鍔?1锛屽苟鎵ц transfer(tab, nt)锛屼箣鍚庡彲鑳芥槸缁х画 sizeCtl 鍔?1锛屽苟鎵ц transfer(tab, nt)銆?/p>

鎵€浠ワ紝鍙兘鐨勬搷浣滃氨鏄墽琛?nbsp;1 娆?transfer(tab, null) + 澶氭 transfer(tab, nt)锛岃繖閲屾€庝箞缁撴潫寰幆鐨勯渶瑕佺湅瀹?transfer 婧愮爜鎵嶆竻妤氥€?/p>

鏁版嵁杩佺Щ锛歵ransfer

涓嬮潰杩欎釜鏂规硶寰堢偣闀匡紝灏嗗師鏉ョ殑 tab 鏁扮粍鐨勫厓绱犺縼绉诲埌鏂扮殑 nextTab 鏁扮粍涓€?/p>

铏界劧鎴戜滑涔嬪墠璇寸殑 tryPresize 鏂规硶涓娆¤皟鐢?transfer 涓嶆秹鍙婂绾跨▼锛屼絾鏄繖涓?transfer 鏂规硶鍙互鍦ㄥ叾浠栧湴鏂硅璋冪敤锛屽吀鍨嬪湴锛屾垜浠箣鍓嶅湪璇?put 鏂规硶鐨勬椂鍊欏氨璇磋繃浜嗭紝璇峰線涓婄湅 put 鏂规硶锛屾槸涓嶆槸鏈変釜鍦版柟璋冪敤浜?helpTransfer 鏂规硶锛宧elpTransfer 鏂规硶浼氳皟鐢?transfer 鏂规硶鐨勩€?/p>

姝ゆ柟娉曟敮鎸佸绾跨▼鎵ц锛屽鍥磋皟鐢ㄦ鏂规硶鐨勬椂鍊欙紝浼氫繚璇佺涓€涓彂璧锋暟鎹縼绉荤殑绾跨▼锛宯extTab 鍙傛暟涓?null锛屼箣鍚庡啀璋冪敤姝ゆ柟娉曠殑鏃跺€欙紝nextTab 涓嶄細涓?null銆?/p>

闃呰婧愮爜涔嬪墠锛屽厛瑕佺悊瑙e苟鍙戞搷浣滅殑鏈哄埗銆傚師鏁扮粍闀垮害涓?n锛屾墍浠ユ垜浠湁 n 涓縼绉讳换鍔★紝璁╂瘡涓嚎绋嬫瘡娆¤礋璐d竴涓皬浠诲姟鏄渶绠€鍗曠殑锛屾瘡鍋氬畬涓€涓换鍔″啀妫€娴嬫槸鍚︽湁鍏朵粬娌″仛瀹岀殑浠诲姟锛屽府鍔╄縼绉诲氨鍙互浜嗭紝鑰?Doug Lea 浣跨敤浜嗕竴涓?stride锛岀畝鍗曠悊瑙e氨鏄闀匡紝姣忎釜绾跨▼姣忔璐熻矗杩佺Щ鍏朵腑鐨勪竴閮ㄥ垎锛屽姣忔杩佺Щ 16 涓皬浠诲姟銆傛墍浠ワ紝鎴戜滑灏遍渶瑕佷竴涓叏灞€鐨勮皟搴﹁€呮潵瀹夋帓鍝釜绾跨▼鎵ц鍝嚑涓换鍔★紝杩欎釜灏辨槸灞炴€?transferIndex 鐨勪綔鐢ㄣ€?/p>

绗竴涓彂璧锋暟鎹縼绉荤殑绾跨▼浼氬皢 transferIndex 鎸囧悜鍘熸暟缁勬渶鍚庣殑浣嶇疆锛岀劧鍚庝粠鍚庡線鍓嶇殑 stride 涓换鍔″睘浜庣涓€涓嚎绋嬶紝鐒跺悗灏?transferIndex 鎸囧悜鏂扮殑浣嶇疆锛屽啀寰€鍓嶇殑 stride 涓换鍔″睘浜庣浜屼釜绾跨▼锛屼緷姝ょ被鎺ㄣ€傚綋鐒讹紝杩欓噷璇寸殑绗簩涓嚎绋嬩笉鏄湡鐨勪竴瀹氭寚浠d簡绗簩涓嚎绋嬶紝涔熷彲浠ユ槸鍚屼竴涓嚎绋嬶紝杩欎釜璇昏€呭簲璇ヨ兘鐞嗚В鍚с€傚叾瀹炲氨鏄皢涓€涓ぇ鐨勮縼绉讳换鍔″垎涓轰簡涓€涓釜浠诲姟鍖呫€?/p>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
private final void transfer(Node<K,V>[] tab, Node<K,V>[] nextTab) {
    int n = tab.length, stride;
 
    // stride 鍦ㄥ崟鏍镐笅鐩存帴绛変簬 n锛屽鏍告ā寮忎笅涓?(n>>>3)/NCPU锛屾渶灏忓€兼槸 16
    // stride 鍙互鐞嗚В涓衡€濇闀库€滐紝鏈?n 涓綅缃槸闇€瑕佽繘琛岃縼绉荤殑锛?/code>
    //   灏嗚繖 n 涓换鍔″垎涓哄涓换鍔″寘锛屾瘡涓换鍔″寘鏈?stride 涓换鍔?/code>
    if ((stride = (NCPU > 1) ? (n >>> 3) / NCPU : n) < MIN_TRANSFER_STRIDE)
        stride = MIN_TRANSFER_STRIDE; // subdivide range
 
    // 濡傛灉 nextTab 涓?null锛屽厛杩涜涓€娆″垵濮嬪寲
    //    鍓嶉潰鎴戜滑璇翠簡锛屽鍥翠細淇濊瘉绗竴涓彂璧疯縼绉荤殑绾跨▼璋冪敤姝ゆ柟娉曟椂锛屽弬鏁?nextTab 涓?null
    //       涔嬪悗鍙備笌杩佺Щ鐨勭嚎绋嬭皟鐢ㄦ鏂规硶鏃讹紝nextTab 涓嶄細涓?null
    if (nextTab == null) {
        try {
            // 瀹归噺缈诲€?/code>
            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 鏄?ConcurrentHashMap 涓殑灞炴€?/code>
        nextTable = nextTab;
        // transferIndex 涔熸槸 ConcurrentHashMap 鐨勫睘鎬э紝鐢ㄤ簬鎺у埗杩佺Щ鐨勪綅缃?/code>
        transferIndex = n;
    }
 
    int nextn = nextTab.length;
 
    // ForwardingNode 缈昏瘧杩囨潵灏辨槸姝e湪琚縼绉荤殑 Node
    // 杩欎釜鏋勯€犳柟娉曚細鐢熸垚涓€涓狽ode锛宬ey銆乿alue 鍜?next 閮戒负 null锛屽叧閿槸 hash 涓?MOVED
    // 鍚庨潰鎴戜滑浼氱湅鍒帮紝鍘熸暟缁勪腑浣嶇疆 i 澶勭殑鑺傜偣瀹屾垚杩佺Щ宸ヤ綔鍚庯紝
    //    灏变細灏嗕綅缃?i 澶勮缃负杩欎釜 ForwardingNode锛岀敤鏉ュ憡璇夊叾浠栫嚎绋嬭浣嶇疆宸茬粡澶勭悊杩囦簡
    //    鎵€浠ュ畠鍏跺疄鐩稿綋浜庢槸涓€涓爣蹇椼€?/code>
    ForwardingNode<K,V> fwd = new ForwardingNode<K,V>(nextTab);
 
 
    // advance 鎸囩殑鏄仛瀹屼簡涓€涓綅缃殑杩佺Щ宸ヤ綔锛屽彲浠ュ噯澶囧仛涓嬩竴涓綅缃殑浜?/code>
    boolean advance = true;
    boolean finishing = false; // to ensure sweep before committing nextTab
 
    /*
     * 涓嬮潰杩欎釜 for 寰幆锛屾渶闅剧悊瑙g殑鍦ㄥ墠闈紝鑰岃鐪嬫噦瀹冧滑锛屽簲璇ュ厛鐪嬫噦鍚庨潰鐨勶紝鐒跺悗鍐嶅€掑洖鏉ョ湅
     *
     */
 
    // i 鏄綅缃储寮曪紝bound 鏄竟鐣岋紝娉ㄦ剰鏄粠鍚庡線鍓?/code>
    for (int i = 0, bound = 0;;) {
        Node<K,V> f; int fh;
 
        // 涓嬮潰杩欎釜 while 鐪熺殑鏄笉濂界悊瑙?/code>
        // advance 涓?true 琛ㄧず鍙互杩涜涓嬩竴涓綅缃殑杩佺Щ浜?/code>
        //   绠€鍗曠悊瑙g粨灞€锛歩 鎸囧悜浜?transferIndex锛宐ound 鎸囧悜浜?transferIndex-stride
        while (advance) {
            int nextIndex, nextBound;
            if (--i >= bound || finishing)
                advance = false;
 
            // 灏?transferIndex 鍊艰祴缁?nextIndex
            // 杩欓噷 transferIndex 涓€鏃﹀皬浜庣瓑浜?0锛岃鏄庡師鏁扮粍鐨勬墍鏈変綅缃兘鏈夌浉搴旂殑绾跨▼鍘诲鐞嗕簡
            else if ((nextIndex = transferIndex) <= 0) {
                i = -1;
                advance = false;
            }
            else if (U.compareAndSwapInt
                     (this, TRANSFERINDEX, nextIndex,
                      nextBound = (nextIndex > stride ?
                                   nextIndex - stride : 0))) {
                // 鐪嬫嫭鍙蜂腑鐨勪唬鐮侊紝nextBound 鏄繖娆¤縼绉讳换鍔$殑杈圭晫锛屾敞鎰忥紝鏄粠鍚庡線鍓?/code>
                bound = nextBound;
                i = nextIndex - 1;
                advance = false;
            }
        }
        if (i < 0 || i >= n || i + n >= nextn) {
            int sc;
            if (finishing) {
                // 鎵€鏈夌殑杩佺Щ鎿嶄綔宸茬粡瀹屾垚
                nextTable = null;
                // 灏嗘柊鐨?nextTab 璧嬪€肩粰 table 灞炴€э紝瀹屾垚杩佺Щ
                table = nextTab;
                // 閲嶆柊璁$畻 sizeCtl锛歯 鏄師鏁扮粍闀垮害锛屾墍浠?sizeCtl 寰楀嚭鐨勫€煎皢鏄柊鏁扮粍闀垮害鐨?0.75 鍊?/code>
                sizeCtl = (n << 1) - (n >>> 1);
                return;
            }
 
            // 涔嬪墠鎴戜滑璇磋繃锛宻izeCtl 鍦ㄨ縼绉诲墠浼氳缃负 (rs << RESIZE_STAMP_SHIFT) + 2
            // 鐒跺悗锛屾瘡鏈変竴涓嚎绋嬪弬涓庤縼绉诲氨浼氬皢 sizeCtl 鍔?1锛?/code>
            // 杩欓噷浣跨敤 CAS 鎿嶄綔瀵?sizeCtl 杩涜鍑?1锛屼唬琛ㄥ仛瀹屼簡灞炰簬鑷繁鐨勪换鍔?/code>
            if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, sc - 1)) {
                // 浠诲姟缁撴潫锛屾柟娉曢€€鍑?/code>
                if ((sc - 2) != resizeStamp(n) << RESIZE_STAMP_SHIFT)
                    return;
 
                // 鍒拌繖閲岋紝璇存槑 (sc - 2) == resizeStamp(n) << RESIZE_STAMP_SHIFT锛?/code>
                // 涔熷氨鏄锛屾墍鏈夌殑杩佺Щ浠诲姟閮藉仛瀹屼簡锛屼篃灏变細杩涘叆鍒颁笂闈㈢殑 if(finishing){} 鍒嗘敮浜?/code>
                finishing = advance = true;
                i = n; // recheck before commit
            }
        }
        // 濡傛灉浣嶇疆 i 澶勬槸绌虹殑锛屾病鏈変换浣曡妭鐐癸紝閭d箞鏀惧叆鍒氬垰鍒濆鍖栫殑 ForwardingNode 鈥濈┖鑺傜偣鈥?/code>
        else if ((f = tabAt(tab, i)) == null)
            advance = casTabAt(tab, i, null, fwd);
        // 璇ヤ綅缃鏄竴涓?ForwardingNode锛屼唬琛ㄨ浣嶇疆宸茬粡杩佺Щ杩囦簡
        else if ((fh = f.hash) == MOVED)
            advance = true; // already processed
        else {
            // 瀵规暟缁勮浣嶇疆澶勭殑缁撶偣鍔犻攣锛屽紑濮嬪鐞嗘暟缁勮浣嶇疆澶勭殑杩佺Щ宸ヤ綔
            synchronized (f) {
                if (tabAt(tab, i) == f) {
                    Node<K,V> ln, hn;
                    // 澶寸粨鐐圭殑 hash 澶т簬 0锛岃鏄庢槸閾捐〃鐨?Node 鑺傜偣
                    if (fh >= 0) {
                        // 涓嬮潰杩欎竴鍧楀拰 Java7 涓殑 ConcurrentHashMap 杩佺Щ鏄樊涓嶅鐨勶紝
                        // 闇€瑕佸皢閾捐〃涓€鍒嗕负浜岋紝
                        //   鎵惧埌鍘熼摼琛ㄤ腑鐨?lastRun锛岀劧鍚?lastRun 鍙婂叾涔嬪悗鐨勮妭鐐规槸涓€璧疯繘琛岃縼绉荤殑
                        //   lastRun 涔嬪墠鐨勮妭鐐归渶瑕佽繘琛屽厠闅嗭紝鐒跺悗鍒嗗埌涓や釜閾捐〃涓?/code>
                        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);
                        }
                        // 鍏朵腑鐨勪竴涓摼琛ㄦ斁鍦ㄦ柊鏁扮粍鐨勪綅缃?i
                        setTabAt(nextTab, i, ln);
                        // 鍙︿竴涓摼琛ㄦ斁鍦ㄦ柊鏁扮粍鐨勪綅缃?i+n
                        setTabAt(nextTab, i + n, hn);
                        // 灏嗗師鏁扮粍璇ヤ綅缃璁剧疆涓?fwd锛屼唬琛ㄨ浣嶇疆宸茬粡澶勭悊瀹屾瘯锛?/code>
                        //    鍏朵粬绾跨▼涓€鏃︾湅鍒拌浣嶇疆鐨?hash 鍊间负 MOVED锛屽氨涓嶄細杩涜杩佺Щ浜?/code>
                        setTabAt(tab, i, fwd);
                        // advance 璁剧疆涓?true锛屼唬琛ㄨ浣嶇疆宸茬粡杩佺Щ瀹屾瘯
                        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;
                            }
                        }
                        // 濡傛灉涓€鍒嗕负浜屽悗锛岃妭鐐规暟灏戜簬 8锛岄偅涔堝皢绾㈤粦鏍戣浆鎹㈠洖閾捐〃
                        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;
 
                        // 灏?ln 鏀剧疆鍦ㄦ柊鏁扮粍鐨勪綅缃?i
                        setTabAt(nextTab, i, ln);
                        // 灏?hn 鏀剧疆鍦ㄦ柊鏁扮粍鐨勪綅缃?i+n
                        setTabAt(nextTab, i + n, hn);
                        // 灏嗗師鏁扮粍璇ヤ綅缃璁剧疆涓?fwd锛屼唬琛ㄨ浣嶇疆宸茬粡澶勭悊瀹屾瘯锛?/code>
                        //    鍏朵粬绾跨▼涓€鏃︾湅鍒拌浣嶇疆鐨?hash 鍊间负 MOVED锛屽氨涓嶄細杩涜杩佺Щ浜?/code>
                        setTabAt(tab, i, fwd);
                        // advance 璁剧疆涓?true锛屼唬琛ㄨ浣嶇疆宸茬粡杩佺Щ瀹屾瘯
                        advance = true;
                    }
                }
            }
        }
    }
}

璇村埌搴曪紝transfer 杩欎釜鏂规硶骞舵病鏈夊疄鐜版墍鏈夌殑杩佺Щ浠诲姟锛屾瘡娆¤皟鐢ㄨ繖涓柟娉曞彧瀹炵幇浜?transferIndex 寰€鍓?stride 涓綅缃殑杩佺Щ宸ヤ綔锛屽叾浠栫殑闇€瑕佺敱澶栧洿鏉ユ帶鍒躲€?/p>

杩欎釜鏃跺€欙紝鍐嶅洖鍘讳粩缁嗙湅 tryPresize 鏂规硶鍙兘灏变細鏇村姞娓呮櫚涓€浜涗簡銆?/p>

get 杩囩▼鍒嗘瀽

get 鏂规硶浠庢潵閮芥槸鏈€绠€鍗曠殑锛岃繖閲屼篃涓嶄緥澶栵細

  1. 璁$畻 hash 鍊?/li>
  2. 鏍规嵁 hash 鍊兼壘鍒版暟缁勫搴斾綅缃? (n 鈥?1) & h
  3. 鏍规嵁璇ヤ綅缃缁撶偣鎬ц川杩涜鐩稿簲鏌ユ壘
    • 濡傛灉璇ヤ綅缃负 null锛岄偅涔堢洿鎺ヨ繑鍥?null 灏卞彲浠ヤ簡
    • 濡傛灉璇ヤ綅缃鐨勮妭鐐瑰垰濂藉氨鏄垜浠渶瑕佺殑锛岃繑鍥炶鑺傜偣鐨勫€煎嵆鍙?/li>
    • 濡傛灉璇ヤ綅缃妭鐐圭殑 hash 鍊煎皬浜?0锛岃鏄庢鍦ㄦ墿瀹癸紝鎴栬€呮槸绾㈤粦鏍戯紝鍚庨潰鎴戜滑鍐嶄粙缁?find 鏂规硶
    • 濡傛灉浠ヤ笂 3 鏉¢兘涓嶆弧瓒筹紝閭e氨鏄摼琛紝杩涜閬嶅巻姣斿鍗冲彲
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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;
        }
        // 濡傛灉澶寸粨鐐圭殑 hash 灏忎簬 0锛岃鏄?姝e湪鎵╁锛屾垨鑰呰浣嶇疆鏄孩榛戞爲
        else if (eh < 0)
            // 鍙傝€?ForwardingNode.find(int h, Object k) 鍜?TreeBin.find(int h, Object k)
            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;
}

绠€鍗曡涓€鍙ワ紝姝ゆ柟娉曠殑澶ч儴鍒嗗唴瀹归兘寰堢畝鍗曪紝鍙湁姝eソ纰板埌鎵╁鐨勬儏鍐碉紝ForwardingNode.find(int h, Object k) 绋嶅井澶嶆潅涓€浜涳紝涓嶈繃鍦ㄤ簡瑙d簡鏁版嵁杩佺Щ鐨勮繃绋嬪悗锛岃繖涓篃灏变笉闅句簡锛屾墍浠ラ檺浜庣瘒骞呰繖閲屼篃涓嶅睍寮€璇翠簡銆?/p>

鎬荤粨

          鍏跺疄涔熶笉鏄緢闅惧槢锛岃櫧鐒舵病鏈変竴琛屼竴琛屾簮鐮佽繘琛屽垎鏋愶紝浣嗚繕鏄妸鎵€鏈夊垵瀛﹁€呭彲鑳戒細绯婃秱鐨勫湴鏂归兘杩涜浜嗘繁鍏ョ殑浠嬬粛锛屽彧瑕佹槸绋嶅井鏈夌偣鍩虹鐨勮鑰咃紝搴旇鏄緢瀹规槗灏辫兘鐪嬫噦 HashMap 鍜?ConcurrentHashMap 婧愮爜浜嗐€傜湅婧愮爜涓嶇畻鏄洰鐨勶紝娣卞叆鍦颁簡瑙?Doug Lea 鐨勮璁℃€濊矾锛屾垜瑙夊緱杩樻尯鏈夎叮鐨勶紝澶у笀灏辨槸澶у笀锛屼唬鐮佸啓寰楃湡鐨勬槸濂藉晩銆?/p>

 

以上是关于Java7/8 涓?HashMap 鍜?ConcurrentHashMap婧愮爜瀵规瘮鍒嗘瀽的主要内容,如果未能解决你的问题,请参考以下文章

Python 涓?Type 鍜?Object

Vue涓殑 el 鍜?mount 鎸傝浇

Java7/8集合框架——HashMap

Java7/8 中的 HashMap 和 ConcurrentHashMap 全解析

Java7/8 HashMap ConcurrentHashMap

Java7/8中的HashMap和ConcurrentHashMap全解析