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 。