在学习了hashMap之后了解到hashMap的各种方法没有加synchornized关键字,也就是说存在线程操作不安全等问题,形成所谓的HashMap环。
- 在这之前我们首先需要了解到HashMap的扩容机制
那么hashmap什么时候进行扩容呢?当hashmap中的元素个数超过数组大小loadFactor时,就会进行数组扩容,loadFactor的默认值为0.75,也就是说,默认情况下,数组大小为16,那么当hashmap中元素个数超过160.75=12的时候,就把数组的大小扩展为2×16=32,即扩大一倍,然后重新计算每个元素在数组中的位置,而这是一个非常消耗性能的操作,所以如果我们已经预知hashmap中元素的个数,那么预设元素的个数能够有效的提高hashmap的性能。比如说,我们有1000个元素new HashMap(1000), 但是理论上来讲new HashMap(1024)更合适,即使是1000,hashmap也自动会将其设置为1024。 但是new HashMap(1024)还不是更合适的,因为0.751000 < 1000, 也就是说为了让0.75 * size > 1000, 我们必须这样new HashMap(2048)才最合适,既考虑了&的问题,也避免了resize的问题。 (有一个小细节是不是当size达到 0.75的时候就会进行扩容,而是既要满足当前元素插入进去的时候size大于等于0.75 并且插入的元素的位置不为空)
- 怎么进行扩容后的元素转移?
我们来查看一下源代码
这里最重要的就是最后三排的代码
第一步将e元素的下连接点指向新开辟的数组对应的位置
第二步将e元素的值赋值给newTable[i]
第三步转移下一个元素。
转移过后应该是这样子的
可以发现顺序被掉头了。
假设现在有线程A,B。A已经完成了扩容
现在B开始扩容,扩容在循环两次后会变成
可以看到有个循环出现,很多网友称为:“死锁”,实则是个死循环。所以产生了环。