其实这个问题不值得分析,已经定位到是并发下HashMap造成的满cpu,直接换成ConcurrentHashMap就行了,本来HashMap就不是线程安全的,HashMap的每一个bucket都是一个链表,并发下操作链表不做同步处理,肯定容易出现循环链表,就死循环了
-
HashMap如果误用到了并发场景很容易出现死循环现象,原因就是在put时进行扩容resize方法中,从老数组拷贝数据到扩容后的新数组造成的
示例
假设线程1执行完 Entry<K,V> next = e.next停住,线程2执行完了transfer方法,线程1再次执行就会有死循环,参考上图。下文代码为jdk7的,jdk8中对bucket上的链表使用了红黑树优化,代码变了很多
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执行完这句停住,线程2执行完了transfer方法,线程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);
}
}
}
网友评论