博客
关于我
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/

    你可能感兴趣的文章
    nodejs连接mysql
    查看>>
    NodeJs连接Oracle数据库
    查看>>
    nodejs配置express服务器,运行自动打开浏览器
    查看>>
    NodeMCU教程 http请求获取Json中文乱码解决方案
    查看>>
    Nodemon 深入解析与使用
    查看>>
    NodeSession:高效且灵活的Node.js会话管理工具
    查看>>
    node~ http缓存
    查看>>
    node不是内部命令时配置node环境变量
    查看>>
    node中fs模块之文件操作
    查看>>
    Node中同步与异步的方式读取文件
    查看>>
    node中的get请求和post请求的不同操作【node学习第五篇】
    查看>>
    Node中的Http模块和Url模块的使用
    查看>>
    Node中自启动工具supervisor的使用
    查看>>
    Node入门之创建第一个HelloNode
    查看>>
    node全局对象 文件系统
    查看>>
    Node出错导致运行崩溃的解决方案
    查看>>
    Node响应中文时解决乱码问题
    查看>>
    node基础(二)_模块以及处理乱码问题
    查看>>
    node安装卸载linux,Linux运维知识之linux 卸载安装node npm
    查看>>
    node安装及配置之windows版
    查看>>