方法不长,总共只有15行代码,但却是造成死循环的关键地方。 红框中的代码就是造成HashMap死循环的原因,现在我们假设原数组中的第一个元素为一个链表 2–>4,如下图所示:
2--->4 |
现在我们复现一下它是如何转换元素的,假设rehash 为 false,我们看下while 中的第一次遍历是什么样的:
上图可以看到e 为元素2,e.next 为元素 4,而 newTable 为新数组,所以 newTable[i] 是为null 的,while中第一次遍历结束后,我们看下新数组的元素存储情况:
2--->null |
现在我们看下while 中的第二次遍历:
上图中可以看到 e 为元素4 ,而由于元素4和元素2是在原数组的同一个位置中的,所以他们的 e.hash 的值是一样的,这样算出来的下标 **i 也是一样的,**这样 newTable[i] 就是上一个元素 2。 所以 e.next=2, newTable[i]=4 , 继续往下走,next 为null则循环结束。我们继续看下新数组中的元素存储情况:
4--->2 |
可以看到链表中的元素被反转了过来,这是因为jdk1.7 中HashMap 在扩容时转换元素的时候,若同一个位置有多个元素,则会采用头插法方式将元素放入新数组,也就是元素始终会在原来元素的头部插入。
我们假设现在有A,B2个线程,A 线程第一次循环结束后,在执行到592行的时候被挂起了。现在B线程进来执行完了2次循环,将4指向2,B结束,A继续执行,就出现2–>4, 4–>2的死循环情况。
我们继续看下jdk1.8 Hashmap 在多线程的情况下扩容的操作源码:
话不多说,直接看 resize 方法:
在查看resize方法时,突然觉得有可以优化的点,于是写了这篇resize优化,虽然推理过程不准确的,但整个思考过程比较完整,有兴趣的可以看看。
由于处于同一位置的哈希值大部分情况是不同的,而 e.hash & oldCap 只会有2种情况,等于0和不等于0,所以采用 loHead,loTail 和 hiHead,hiTail 这四个变量进行区分,而 loTail.next = null; 和 hiTail.next = null; 这2行的效果一样都是为了避免数据重复。
代码很长,我们着重看下722-726行 和 736-739行,还是2–>4 ,我们看下它2次的数据转换情况,第一次循环:
第一次循环loTail 为null, 所以 loHead 和 loTail 都等于元素 2 ,第二次循环:
可以看到在第二次循环完成后, 新数组中的 newTab[j] 中的元素还是原来的顺序 2–>4, 所以**即使是在多线程的情况下扩容也不会发生死循环。**但是jdk1.8中的HashMap依然不是线程安全的,是有可能发生数据覆盖的,我们还是看源码:
我们着重看下 630 行 和 631 行,在 630 行 和 631 行 可以看到 hash 与 n-1 按位与(也就是取余) 生成元素下标,然后取出该下标的元素判断是否为空,若为空则将元素放入tab数组中。
现在我们假设有A,B2个线程往HashMap中放入元素, A 线程带着 i=1,value=4 的元素执行到630行时被挂起了,而 B 线程带着i=1,value=5 的元素执行完成,结束。这时A线程继续执行 tab[1]=4 , 结束。这样value=5 的元素就被覆盖。
总结:
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
写在最后
很多人感叹“学习无用”,实际上之所以产生无用论,是因为自己想要的与自己所学的匹配不上,这也就意味着自己学得远远不够。无论是学习还是工作,都应该有主动性,所以如果拥有大厂梦,那么就要自己努力去实现它。
最后祝愿各位身体健康,顺利拿到心仪的offer!
由于文章的篇幅有限,所以这次的蚂蚁金服和京东面试题答案整理在了PDF文档里
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
mg-d4g0Q2Zx-1713751527925)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!