jdk1.7中hashMap扩容导致死循环问题原理分析
作者:互联网
导致死循环的根源是在resize的时候进行元素转移的时候有概率会出现;
先说结论:导致问题的根本原因是使用头插法;
先贴出来源码:
但是哪怕你不看源码也没关系;
void transfer(Entry[] newTable, boolean rehash) {
int newCapacity = newTable.length;
for (Entry<K,V> e : table) {
while(null != e) {
Entry<K,V> next = e.next;
if (rehash) {
e.hash = null == e.key ? 0 : hash(e.key);
}
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
}
}
}
这里呢好多文章通过举例子,画数据结构变化过程的图来进行讲解。不够形象,不易理解。这里我通过一个生活模型来进行讲解;
旅游公司维护旅游路线模型;
如下图,图中路线池子对应的就是hashMap中的数组,每个旅游路线的链表就是hashMap中的hash碰撞产生的链表;
故事是这样的:游客买完了某个旅游路线后,旅游公司会开大巴把你拉到你购买的起点,然后游客自己跟着路标进行旅游即可。旅游公司一直运营的很好。但是偶尔会有时候用户会 投诉说路线有问题,把我们当傻子一样困死在线路中; 但是这种现象经常出现在新加了景点,然后重新维护旅游路线的路标时候,(这里也就对应的是hashMap进行添加元素并且扩容的场景);
我们知道旅游线路都是带有一定文化主题的。在一个线路中的景点在重新维护的的时候很可能还是在一组。但是为了防止游客觉得没有新意,往往仅仅会给路线改个名字,然后把线路倒过来,重新设置路标,然后继续使用(尾插法)
后来经过分析原来是名字叫 病发 的领导经常喝酒,脑袋混了经常同时派多个人去维护同一个路线;
下面我们看看怎么出现问题的;我们已第一条旅游线路来举例子;也就是A->B->C这条路线;
这不这次 病发 先派 小红 去把1路线的路标倒过来排,并且改名为15;然后他没过1秒钟就忘了,然后又派 小黑 也去同时维护同一条路线;
小红是个急性子,想赶快维护好下班回家。小黑是个佛系躺平青年,慢悠悠的弄;
时间 | 小红 | 小黑 |
---|---|---|
1分钟 | 到达A | 到达A |
2分钟 | 1.记下下一个要去处理的景点是B,2.把A挪到15路线开头,3,把A的路标设置为空 | 1.把A挪到15路线开头,2.记下下一个景点是B,把A的路标设置为空 ,并前往B,在去B的的路上玩起了王者荣耀 |
3分钟 | 到达B,记下下一个景点C,把B挪到15路线,并把B的路标设置为A (头插法) | AB路上王者荣耀 |
4分钟 | 到达C,发现没有下一个景点了,把C挪到15路线,并把C的路标设置为B | AB路上要输了,郁闷的往B景点走 |
5分钟 | 完活,赶紧下班回家 | 到达B,把B设置到15路线,把B的下一个景点设置为A(头插法),然后发现下一个要处理的节点是A,前往A |
6分钟 | 到家了 | 到达A,把A设置到15路线,记下当前A的下一个节点是空(心里开心了起来要完工了),然后把A的下一个节点设置为15的当前节点B |
7分钟 | 到家了 | 完工,在回办公室的路上再开了一局 |
第二天 | 又有投诉 | 我*你个** |
最后由小黑维护完成后,景点的路标会出现a指向b,b指向a的情况
到这里就弄明白了为什么hashMap会在并发场景下导致死循环的问题
标签:15,hashMap,路标,jdk1.7,路线,旅游,景点,死循环 来源: https://blog.csdn.net/AngryCoding/article/details/117395198