目录
为什么会出现环链?
HashMap是线程不安全的,并且其扩容的代码会将原来的链表进行反序,例如原先的是 3-> 2-> 1,现在还在同一位置则是 1->2->3,那么在多线程并发操作的情况下一个正序,一个反序,就会有可能出现。
什么时候会出现环链?
多线程操作,同时去扩容,当一个线程已经操作完毕了,将原来的顺序反过来了;另一个线程再开始执行扩容代码,此时就会出现环链。
正常的扩容转移效果如下:
代码运行的结果如下:
出现环链的场景:
数据准备、结果预期
首先初始化一个数组,数组的一个元素是一个链表,有三个对象,模拟扩容的操作,将其中的一个分散到新数组的一个槽位中,将剩余的两个仍形成一个链表的结构。
模拟的转移代码
散列的函数粗糙点,主要是为了达到两个元素存在于一个槽位的目的
public static void transfer(Entry[] newTable, Entry[] table) {
for (Entry e : table) {
while (e != null) {
//1 、拿出下一个以及后面的所有
Entry next = e.next;
// 散列效果看i的分布
int i = Integer.parseInt(e.key) > 1 ? 1 : 0;
// 2、断开e与之前的,指向新的;新的可能是空,也可能有对象 ,有对象的话就是头插法
e.next = newTable[i];
// 3、再把E新操作后的一串对象赋值给新的数组。 2/3这两步实现头插转移
newTable[i] = e;
//4、指针移动到下一个,直到结束
e =