博客
关于我
Java——Java基础之ConcurrentHashMap
阅读量:336 次
发布时间:2019-03-04

本文共 2018 字,大约阅读时间需要 6 分钟。

put 方法

put 操作是 ConcurrentHashMap 中最常见的操作之一。在 putVal 方法中,如果发现当前线程的 hash 碰撞(即当前 hash 值对应的槽位已经有值),并且该值为 -1(表示 MOVED),那么说明 Map 正在扩容。此时,helpTransfer 方法会被调用以协助扩容,以加快扩容速度。


transfer 扩容方法

transfer 方法负责将 Map 的元素从当前表中扩展到更大的表中。当 Map 的当前表已达到扩容阈值时,transfer 方法会被调用。具体来说:

  • 通过 resizeStamp 方法获取当前表的长度。
  • 如果 sizeCtl 的低 16 位不等于 resizeStamp,或者 sizeCtl 已经超过了阈值,或者 nextTable 为空,或者 transferIndex 小于等于 0,则终止扩容。
  • 如果可以帮助扩容(即 sizeCtl 小于阈值),则将 sizeCtl 加 1,表示有多个线程在协助扩容。
  • 如果不在协助扩容,则将 sizeCtl 更新为 resizeStamp + 2,表示当前线程将独立进行扩容。

  • helpTransfer 帮助扩容方法

    helpTransfer 方法的主要作用是协助扩容。当 putVal 方法检测到当前 hash 碰撞(槽位已存在且值为 MOVED)时,会调用 helpTransfer 方法。该方法通过 fullAddCount 方法进行扩容操作。


    size 方法 / mappingCount 方法

    ConcurrentHashMap 的 size 方法返回当前 Map 中键值对的数量,但其最大值为 Integer.MAX_VALUE。由于 Map 的实际数量可能超过 Integer.MAX_VALUE,JDK 建议使用 mappingCount 方法代替 size 方法。

    public int size() {    long n = sumCount();    return ((n < 0L) ? 0 :             (n > (long)Integer.MAX_VALUE) ? Integer.MAX_VALUE :             (int)n);}public long mappingCount() {    long n = sumCount();    return (n < 0L) ? 0L : n;}

    sumCount 方法

    sumCount 方法用于统计 Map 中键值对的总数量。它通过遍历 counterCells 数组,累加每个 CounterCell 的 value。具体流程如下:

  • 初始化 sum 为 baseCount。
  • 如果 counterCells 不为空,则遍历 counterCells 数组,累加每个 cell 的 value 到 sum 中。
  • 返回 sum。

  • put 方法

    put 方法用于将键值对插入 Map 中。它会调用 putVal 方法,并在成功插入后调用 addCount 方法来更新计数器。

    public V put(K key, V value) {    return putVal(key, value, false);}final V putVal(K key, V value, boolean onlyIfAbsent) {    // ...(内部逻辑)    addCount(1L, binCount);    return null;}

    addCount 方法

    addCount 方法用于更新 Map 的计数器。它通过 CAS 操作尝试直接更新 baseCount。如果 CAS 操作失败,则通过 fullAddCount 方法进行批量更新。

  • 如果 counterCells 为空或 baseCount 更新失败,则执行 fullAddCount 方法。
  • fullAddCount 方法会递增 binCount,直到操作成功。

  • 扩容逻辑

    当 Map 达到扩容阈值时,sizeCtl 会被更新为负值,表示需要扩容。具体流程如下:

  • 通过 resizeStamp 方法获取当前表的长度。
  • 如果 sizeCtl 的低 16 位不等于 resizeStamp,或者 sizeCtl 已经超过了阈值,或者 nextTable 为空,或者 transferIndex 小于等于 0,则终止扩容。
  • 如果可以帮助扩容(即 sizeCtl 小于阈值),则将 sizeCtl 加 1,表示有多个线程在协助扩容。
  • 如果不在协助扩容,则将 sizeCtl 更新为 resizeStamp + 2,表示当前线程将独立进行扩容。

  • 通过以上方法,ConcurrentHashMap 实现了高效的线程安全 Map,能够在多线程环境下保持良好的性能。

    转载地址:http://wmeh.baihongyu.com/

    你可能感兴趣的文章
    Neutron系列 : Neutron OVS OpenFlow 流表 和 L2 Population(7)
    查看>>
    New Relic——手机应用app开发达人的福利立即就到啦!
    查看>>
    NFinal学习笔记 02—NFinalBuild
    查看>>
    NFS
    查看>>
    NFS Server及Client配置与挂载详解
    查看>>
    NFS共享文件系统搭建
    查看>>
    nfs复习
    查看>>
    NFS安装配置
    查看>>
    NFS的安装以及windows/linux挂载linux网络文件系统NFS
    查看>>
    NFS的常用挂载参数
    查看>>
    NFS网络文件系统
    查看>>
    nft文件传输_利用remoting实现文件传输-.NET教程,远程及网络应用
    查看>>
    NFV商用可行新华三vBRAS方案实践验证
    查看>>
    ng build --aot --prod生成文件报错
    查看>>
    ng 指令的自定义、使用
    查看>>
    nghttp3使用指南
    查看>>
    Nginx
    查看>>
    nginx + etcd 动态负载均衡实践(三)—— 基于nginx-upsync-module实现
    查看>>
    nginx + etcd 动态负载均衡实践(二)—— 组件安装
    查看>>
    nginx + etcd 动态负载均衡实践(四)—— 基于confd实现
    查看>>