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

    你可能感兴趣的文章
    Python 多处理 apply_async 永远不会在 Windows 7 上返回结果
    查看>>
    Python 多处理 Numpy 随机
    查看>>
    Python 多处理 >= 125 列表永远不会完成
    查看>>
    Python 多处理:在第一个子错误时中止映射
    查看>>
    Python 多处理不断产生 pythonw.exe 进程而不做任何实际工作
    查看>>
    Python 多处理从不加入
    查看>>
    Python 多处理如何优雅地退出?
    查看>>
    Python 多处理将子进程的标准输出重定向到 Tkinter 文本
    查看>>
    Python 多处理库错误(AttributeError:__exit__)
    查看>>
    Python 多处理模块的 .join() 方法到底在做什么?
    查看>>
    python 多线程与GIL
    查看>>
    Python 多线程学习(转)
    查看>>
    python 多进程-基础
    查看>>
    python 多进程-进阶-进程池
    查看>>
    python 多进程-进阶-进程间通信之Pipe
    查看>>
    python 多进程-进阶-进程间通信之Queue
    查看>>
    Python编程快速入门
    查看>>
    Python编程基础(附Pycharm与开发环境)
    查看>>
    python 如何“否定“value : 如果为真则返回假,如果为假则返回真
    查看>>
    Python 如何在 Web 环境中使用 Matplotlib 进行数据可视化
    查看>>