HASMAP结构图

为什么HashMap是线程不安全的

1.如果多个线程同时使用put方法添加元素会丢失元素

假设正好存在两个put的key发生了碰撞,那么根据HashMap的实现,这两个key会添加到数组的同一个位置,这样最终就会发生其中一个线程的put的数据被覆盖。

2.多线程同时扩容会造成死循环

多线程同时检查到扩容,并且执行扩容操作,在进行rehash的时候会造成闭环链表,从而在get该位置元素的时候,程序将会进入死循环。【证明HashMap高并发下问题会在以后的文章中出现】

如何让HashMap实现线程安全?

  1. 直接使用Hashtable
  2. Collections.synchronizeMap方法
  3. 使用ConcurrentHashMap

总结

  1. HashMap 在第一次 put 时初始化,类似 ArrayList 在第一次 add 时分配空间。
  2. HashMap 的 bucket 数组大小一定是2的n次方
  3. HashMap 在 put 的元素数量大于 Capacity * LoadFactor(默认16 * 0.75) 之后会进行扩容
  4. 负载因子是可以修改的,也可以大于1,但是建议不要轻易修改,除非情况非常特殊
  5. JDK8处于提升性能的考虑,在哈希碰撞的链表长度达到TREEIFY_THRESHOLD(默认8)后,会把该链表转变成树结构
  6. JDK8在 resize 的时候,通过巧妙的设计,减少了 rehash 的性能消耗
  7. 扩容是一个特别耗性能的操作,所以当在使用HashMap的时候,估算map的大小,初始化的时候给一个大致的数值,避免map进行频繁的扩容

java1.8在hashmap的node长度大于8的时候,链表就会装化成红黑树的数据结构来存储节点

 

 

java7ConcurrenHashMap相比HashTable,多了一层segment数组,由于有了这一层,同步锁的粒度更细,每次的操作只对其中某个segment加锁,其他segment的节点是可操作的.而在java8中直接对链表和红黑树加锁,去掉了segment这一层。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值