HashMap在多線程下面出現死循環,這種狀況有點難模擬,千萬別在生成環境出現,一旦出現那就等着哭吧。java
廢話很少說不知道hashmap 如何擴容的先看下源碼可能好理解點。數組
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); table = newTable; threshold = (int) (newCapacity * loadFactor); }
//此方法就是 hashMap 將數據放到新的擴容以後的數組,方法沒啥問題,徹底正確無誤。 void transfer(Entry[] newTable) { Entry[] src = table; int newCapacity = newTable.length; for (int j = 0; j < src.length; j++) { Entry<K, V> e = src[j]; if (e != null) { src[j] = null; do { //過程(1) Entry<K, V> next = e.next; int i = indexFor(e.hash, newCapacity); e.next = newTable[i]; newTable[i] = e; e = next; } while (e != null); } } }
在多線程狀況下,狀況就不同了。模擬一種狀況:數據結構
假設如今HashMap 的table 長度爲2 ,因子爲1 以下圖
多線程
現有線程P1 、P2spa
當P1線程執行到 過程(1)下面的時候線程
此時 e =a1 ,next = a2 P2 進入執行了而且執行完畢code
當前新的結構爲索引
再執行P1 此時獲得的新數組索引和P2 是同樣。 ci
e.next =newTable[i] 即爲 a2 (a2.next =a1)源碼
newTable[i] = e 即爲 a1 數組結構變爲
e=next 即爲 a2 ;
第二次循環的時候
Entry<K, V> next = e.next 即爲a1
e.next = newTable[i]; 即爲 a1 (a1.next = a2)
newTable[i] = e 即爲 a2 數據結構變爲
e=next 即爲 a1 ;
第三次的循環的時候
Entry<K, V> next = e.next 即爲a2
就造成了迴環了。
就成了死循環。
在多線程循環下不要使用hashmap 。