jdk1.7 HashMap in the "fatal error": circular list
jdk1.7 HashMap configuration in FIG.
jdk1.7 is a linked list structure array +
jdk1.7 versions exist two major problems
-
The case will result in the first interpolation cycle chain
-
The list is too long, it will lead to reduced efficiency inquiry
jdk1.8 version optimized for jdk1.8
- Tail using interpolation, elimination occurs circular list
- After the list is too long, into a red-black tree, improve query efficiency
I specifically refer to another article blog you really know manufacturers face questions: HashMap it?
Produce circular list
Multithreading Meanwhile put
, if at the same time calling the resize
operation could lead to circular list is generated, thus making the time to get back, it will be an endless loop. The following detail how circular list form.
resize function
Array expansion function, the main function is to create a new array after the expansion, and calls the transfer
function will migrate the old elements in the array to a new array
void resize(int newCapacity)
{
Entry[] oldTable = table;
int oldCapacity = oldTable.length;
......
//创建一个新的Hash Table
Entry[] newTable = new Entry[newCapacity];
//将Old Hash Table上的数据迁移到New Hash Table上
transfer(newTable);
table = newTable;
threshold = (int)(newCapacity * loadFactor);
}
transfer function
transfer logic is actually simple, traversing the old array, the array element by the old header interpolation manner, the position corresponding to migrate to the new problem lies in an array head interpolation .
void transfer(Entry[] newTable)
{
//src旧数组
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 {
Entry<K,V> next = e.next;
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
} while (e != null);//由于是链表,所以有个循环过程
}
}
}
static int indexFor(int h, int length){
return h&(length-1);
}
Here's an example of practical
//下面详细解释需要用到这部分代码,所以先标号,将一下代码分为五个步骤
do {
1、Entry<K,V> next = e.next;
2、int i = indexFor(e.hash, newCapacity);
3、e.next = newTab[i];
4、newTable[i] = e;
5、e= next;
} while(e != null)
-
Start capacity is set to 2, the threshold value is loaded
-
Thread And thread Meanwhile insert elements, since the threshold value is 1, so the need to call
resize
the function, the operation for expansion -
Thread First blocking the code
Entry<K,V> next = e.next;
, after thread After executing expansion of operations -
After thread Wake up, continue, after the completion of a cycle
Start , , implementation of the following code, ,
2、int i = indexFor(e.hash, newCapacity); 3、e.next = newTab[i]; 4、newTable[i] = e; 5、e= next; 1、Entry<K,V> next = e.next;
-
Thread After the implementation of the second cycle
Start , , the following code is executed, $ e \ rightarrow3 $,
2、int i = indexFor(e.hash, newCapacity); 3、e.next = newTab[i]; 4、newTable[i] = e; 5、e= next; 1、Entry<K,V> next = e.next;
-
After the third cycle execution thread T1, forming an endless loop
Start , , the following code,
2、int i = indexFor(e.hash, newCapacity); 3、e.next = newTab[i]; 4、newTable[i] = e; 5、e= next; 1、Entry<K,V> next = e.next;