Java面试之集合类(2)ConcurrentHashmap

以下内容来自网络整理,侵删
如何求size
  • JDK 8 推荐使用mappingCount 方法,因为这个方法的返回值是 long 类型,不会因为 size 方法是 int 类型限制最大值
  • 在没有并发的情况下,使用一个 volatile 修饰的baseCount 变量就足够了
  • 当并发的时候,CAS 修改 baseCount 失败后,就会使用 CounterCell 类了,会创建一个这个对象,通常对象的 volatile value 属性是 1。在计算 size 的时候,会将 baseCount 和 CounterCell 数组中的元素的 value 累加,得到总的大小,但这个数字仍旧可能是不准确的。
数据结构
JDK1.7
  • 整个 ConcurrentHashMap 由一个个 Segment 组成,Segment 代表”部分“或”一段“的意思,所以很多地方都会将其描述为分段锁。
  • 我们可以把每个 Segment 看成是一个小的 HashMap,其内部结构和 HashMap 是一模一样的

在这里插入图片描述

JDK1.8

在这里插入图片描述

  • 1.8中放弃了Segment分段锁的设计,使用的是Node数组+CAS+Synchronized来保证线程安全性
Put方法
  • 篇幅有限,只介绍JDK1.8的
  • 以下步骤重复循环执行,直到成功:
    • 如果node数组没有初始化,则初始化
    • 通过hash值找到当前 key 所在的桶,并且判断是否为空(冲突),如果为空,则通过CAS 原子操作,把新节点插入到此位置
    • 如果数组正在进行扩容,则需要当前线程帮忙迁移数据
      -如果存在hash冲突,就通过synchronized加锁来保证线程安全,这里有两种情况,一种是链表形式就直接遍历到尾端插入,一种是红黑树就按照红黑树结构插入
    • 最后如果Hash冲突时会形成Node链表,在链表长度超过8会将链表结构转换为红黑树的结构
Get方法
  • 篇幅有限,只介绍JDK1.8的
  • 计算 hash 值
  • 根据 hash 值找到数组对应位置: (n - 1) & h
  • 根据该位置处结点性质进行相应查找
    • 如果该位置为 null,那么直接返回 null 就可以了
    • 如果该位置处的节点刚好就是我们需要的,返回该节点的值即可
    • 如果该位置节点的 hash 值小于 0,说明正在扩容,或者是红黑树,后面我们再调用 find 方法
  • 如果以上 3 条都不满足,那就是链表,进行遍历比对即可
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值