探究ConcurrentHashMap中键值对在Segment[]的下标如何确定

2023-11-15

内容

   本文对JDK1.7下使用segmentShift和segmentMask求解ConcurrentHashMap键值对在Segment[]中的下标值进行了探究和论证。

适合人群

 ​  Java进阶

说明

   转载请注明出处,尊重笔者的劳动成果。

 推荐阅读

   探究HashMap线性不安全(二)——链表成环的详细过程

 正文

   下面先查看ConcurrentHashMap源码中的put操作,找到segment[]的下标j的计算公式。

 1 @SuppressWarnings("unchecked")
 2 public V put(K key, V value) {
 3     Segment<K,V> s;
 4     if (value == null)
 5         throw new NullPointerException();
 6     int hash = hash(key);
 7     //key对应的segment[]的下标j的计算公式
 8     int j = (hash >>> segmentShift) & segmentMask;
 9     if ((s = (Segment<K,V>)UNSAFE.getObject          // nonvolatile; recheck
10          (segments, (j << SSHIFT) + SBASE)) == null) //  in ensureSegment
11         s = ensureSegment(j);
12     return s.put(key, hash, value, false);
13 }

  由上面的ConcurrentHashMap源码可知,一个键值对在Segment数组中下标j的计算公式为:

j = (hash >>> segmentShift) & segmentMask

  公式虽然不长,但是它包含了2个“晦涩难懂”的参数:segmentShift和segmentMask ,让人费解。下面笔者用一种通俗简单的方式来解释该公式的含义。

  首先,阅读ConcurrentHashMap的构造方法,重点查看注释区域,其中包含了segmentShift和segmentMask的定义:

segmentShift = 32 - sshift;segmentMask = ssize - 1;

  以及segment数组长度ssize与sshift的关系:

2^sshif=ssize
  ConcurrentHashMap的构造方法
 1 public ConcurrentHashMap(int initialCapacity,
 2                                float loadFactor, int concurrencyLevel) {
 3           if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0)
 4               throw new IllegalArgumentException();
 5           if (concurrencyLevel > MAX_SEGMENTS)
 6               concurrencyLevel = MAX_SEGMENTS;
 7          int sshift = 0;
 8          int ssize = 1;
 9      //2^sshif=ssize,例:sshift=4,ssize=16;
10    //根据concurrentLevel计算得出ssize为segments数组长度
11          while (ssize < concurrencyLevel) {
12              ++sshift;
13              ssize <<= 1;
14          }
15          //segmentShift和segmentMask的定义
16          this.segmentShift = 32 - sshift;
17          this.segmentMask = ssize - 1;
18          if (initialCapacity > MAXIMUM_CAPACITY)
19              initialCapacity = MAXIMUM_CAPACITY;
20          //计算cap的大小,即Segment中HashEntry的数组长度,cap也一定为2的n次方.
21          int c = initialCapacity / ssize;
22          if (c * ssize < initialCapacity)
23              ++c;
24          int cap = MIN_SEGMENT_TABLE_CAPACITY;
25          while (cap < c)
26              cap <<= 1;
27          //创建segments数组并初始化第一个Segment,其余的Segment延迟初始化
28          Segment<K,V> s0 =
29              new Segment<K,V>(loadFactor, (int)(cap * loadFactor),
30                              (HashEntry<K,V>[])new HashEntry[cap]);
31          Segment<K,V>[] ss = (Segment<K,V>[])new Segment[ssize];
32          UNSAFE.putOrderedObject(ss, SBASE, s0); 
33          this.segments = ss;
34      }

   由此可知,求key散列到长度为ssize的Segment数组的下标j,必定有下标j的值域为[0,ssize-1]。由于ssize=2^sshif,那么小标j可以用1个sshift位的二进制数字表示。假如:ssize为16,那么sshift=4,j的值域为[0,15],而[0000b,1111b]就是j的值域;则求key在Segment[]的下标j,就是求key对应的一个散列的4位二进制数值。而ConcurrentHashMap的源码求下标j的方式非常简单,就是取key的hash值的高4位。因此,求key散列到长度为ssize的Segment数组的下标j,就是求key的hash值的高sshift位。

  故有,j=(key.hash>>>(32-sshift))&(ssize-1)。而由源码可知,segmentShift = 32 - sshift,segmentMask = ssize - 1。即:

j=(key.hash>>>(32-sshift))&(ssize-1)=(key.hash>>>segmentShift )&segmentMask。(其中>>>表示无符号右移,空位补0)

  以ssize为16为例,演示计算过程:

1538405541238

转载于:https://www.cnblogs.com/lonelyJay/p/9736027.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

探究ConcurrentHashMap中键值对在Segment[]的下标如何确定 的相关文章

  • android.view.InflateException:二进制 XML 文件行 #11:膨胀类 ImageView 时出错

    我只是尝试制作一个小的 android java xml 应用程序来计算游戏的分数 它给了我这个错误 Error inflateing class ImageView 有人知道解决方案吗 我实际上搜索了 ppl 说添加这个 android
  • 如何在 Java 中访问嵌套的 HashMap?

    我有一个 Java 中的 HashMap 其中的内容 你们可能都知道 可以通过以下方式访问 HashMap get keyname 如果一个 HashMap 位于另一个 HashMap 中 即嵌套的 HashMap 我将如何访问内容 我可以
  • 如何配置 Spring-WS 以使用 JAXB Marshaller?

    感谢您到目前为止对此的帮助 我正在更新问题 因为我没有显示我需要的所有内容 并显示了建议的更改 肥皂输出仍然不是我想要的 servlet xml
  • Java:线程“主”中的异常 java.lang.StringIndexOutOfBoundsException:字符串索引超出范围:

    我是初学者 谁能帮我弄清楚我们在做什么 我正在尝试读取字符串并将字符串的每个字符存储在数组中 import java util Scanner public class CoreMainDigitExtractor static Scann
  • JTextField 和 JTextArea

    JTextField 和 JTextArea 有什么不同 是否可以在一个班级中使用这两个班级 总之 JTextField 是单行文本字段 而 JTextArea 可以跨越多行 文档中清楚地解释了这些差异 文本区 http docs orac
  • java中的单链表和双向链表?

    在java中 哪个集合接口可以有效地实现单链表和双向链表 请问代码示例吗 毫不奇怪 实现双向链表的正确接口是 LinkedList 看Java文档 http docs oracle com javase 8 docs api java ut
  • Android WebView文件上传

    我正在开发一个 Android 应用程序 基本上它是一个WebView和一个进度条 Facebook 的移动网站 m facebook com 已加载到WebView 当我单击 选择文件 按钮上传图像时 没有任何反应 我已经尝试了所有的解决
  • 需要正则表达式帮助

    我正在尝试替换两次或多次出现的 br like br br br 标签与两个一起 br br 具有以下模式 Pattern brTagPattern Pattern compile lt s br s s gt s 2 Pattern CA
  • Android volley使用RequestFuture.get()时出现超时异常

    在我的片段中 我尝试使用 TMDB 的开放电影数据库来获取有关 正在播放 电影的详细信息 如果我使用 RequestFuture get time TimeUnit 方法来执行此齐射请求 我总是会收到超时错误 如果我在 Safari 中手动
  • Java - JPanel 内有边距和 JTextArea

    我想创建这样的东西 主面板有其边距 x 并且 TextArea 位于该面板的中心 几乎填满了面板 底部是另一个具有自定义尺寸 高度 y 的面板 可以使用某些快捷方式将其切换为可见和不可见 底部面板有 FlowLayout 和几个元素 问题是
  • java.lang.Object的hashCode具体使用的算法是什么

    中使用的算法是什么JVM实施java lang Object的隐含的hashCode 方法 OpenJDK or Oracle JDK答案中首选 它依赖于实现 并且在很大程度上 该算法是entirely取决于实施 只要它是一致的 但是 根据
  • Java 中的 ExecuteUpdate sql 语句不起作用

    我正在学习如何将 SQL 与 Java 结合使用 我已成功安装 JDBC 驱动程序 并且能够从数据库读取记录并将其打印在屏幕上 我的问题发生在尝试执行更新或插入语句时 没有任何反应 这是我的代码 问题所在的方法 public static
  • 将现有 eclipse 项目导出到 war 文件时出现“模块名称无效”

    我正在尝试将现有 Eclipse 项目导出到 war 文件 但无论我在 WAR Export 对话框页面中输入什么 系统总是返回 模块名称无效 我不知道如何解决这个问题 谢谢您的帮助 我有同样的问题 我修复了它 请按照以下步骤操作 您可以创
  • 查找数组中的组合

    我在java中有一个像这样的二维数组 transmission communication tv television approach memorycode methodact 我需要获得所有组合 例如 transmission appr
  • 从 Android 访问云存储

    我一直无法找到任何有关如何从 Android 应用程序使用云存储的具体文档 我确实遇到过这个客户端库 https cloud google com storage docs reference libraries然而 Google Clou
  • Android 解析 JSON 卡在 get 任务上

    我正在尝试解析一些 JSON 数据 我的代码工作了一段时间 我不确定我改变了什么突然破坏了代码 当我运行代码时 我没有收到任何运行时错误或警告 我创建一个新的 AsyncTask 并执行它 当我打电话时 get 在这个新任务中 调试器在此行
  • JAXB 编组器无参数默认构造函数

    我想从 java 库中编组一个 java 对象 当使用 JAXB marschaller 编组 java 对象时 我遇到了一个问题 A 类没有无参数默认构造函数 我使用Java Decompiler来检查类的实现 它是这样的 public
  • Java 中的微分方程

    我正在尝试用java创建一个简单的SIR流行病模型模拟程序 基本上 SIR 由三个微分方程组定义 S t l t S t I t l t S t g t I t R t g t I t S 易感人群 I 感染人群 R 康复人群 l t c
  • @Embeddable 中的 @GenerateValue

    我已将实体的 id 分离到一个单独的 Embeddable 类中 该实体如下 Entity Table name users public class Users EmbeddedId private Users pk id private
  • 使用 AmazonSNSClient 发送短信时的授权

    aws 官方文档如何发送短信 http docs aws amazon com sns latest dg sms publish to phone html使用 java 中的 aws SDK 非常简单 但是 当发送如底部示例所示的消息时

随机推荐

  • React与响应式系统

    响应式系统与React 1 React的历史与应用 React的历史 2010年Facebook在其php生态中引入了xhp框架 首次引入了组合式组件的思想 启发了后来的React的设计 2011年Jordan Walke创造了FaxJs
  • 服务器可以放置多少个网站

    服务器可以放置多少个网站 一 网站大小 能影响一个网站大小的因素是比较多的 例如网站的设计 网站里的内容大小 通常网站尺寸比较大 动态页面比较多的 例如视频网站和小说网站 通常对储存的要求也会比较高 所以网站大小必然还是比较大的 一台主机上
  • linux查看ip地址命令ipconfig命令不存在解决方法

    linux查看ip地址命令ipconfig命令不存在 在新版的Linux发行版中 ipconfig已经不行了 不能使用了 那么 Linux查看ip地址应该使用什么命令呢 如何在Linux命令行中查找系统的IP地址 对于许多Linux用户来说
  • SSM之Mybatis(二)Mapper映射文件

    介绍 Mapper映射文件 作用是用来配置SQL映射语句 根据不同的SQL语句性质 使用不同的标签 mapper文件中常用的标签有
  • 数据可视化库 matplotlib 入门 5——饼图

    Matplotlib 库使用入门5 饼图 pie 函数 绘制饼图示例 在前面关于 matploblib 的文章中 笔者分别介绍了 matplotlib 库的安装与配置 常用套路和绘图组件 画布和绘图域的创建 图素的设置 用 plot 函数绘
  • Springboot使用netty应用tcp协议

    介绍 Netty是由JBOSS提供的一个java开源框架 Netty提供异步的 事件驱动的网络应用程序框架和工具 用以快速开发高性能 高可靠性的网络服务器和客户端程序 也就是说 Netty 是一个基于NIO的客户 服务器端编程框架 使用Ne
  • sass中的占位符%,@extend,@mixin(@include)的编译区别和使用场景

    对于下面同一段css 它们的编译效率是不同的 1 使用 extend 基础类icon会出现在编译后的css文件中 即使它可能只是拿来被继承 而不是作为icon这个class单独使用 基础类icon icon transition backg
  • 因为乘法有一个更高的优先级比加法

    为了正确地评估表达式 如4 2 3 我们必须了解运营商做什么 以及正确的顺序 适用于他们 运算符在复合表达式中计算的顺序称为运算符优先级 使用正常的数学优先规则 在加法之前求解乘法的状态 我们知道上面的表达式应该以4 2 3 来计算 以产生
  • 仓山区工业机器人_重磅!富士康东南总部拟入仓山!或建全国第二家工业互联网学院...

    随着福州城市发展加速 众多知名企业纷纷落地 近日 有消息称 著名企业富士康拟来福州建设东南运营总部和研发中心 富士康拟在仓山建设东南运营总部 10月11日 福州投促局在官网发布消息称 富士康工业富联拟在仓山区落地东南运营总部和研发中心 并合
  • Windows命令行初步:更改配色、提示符以及编码方式

    文章目录 启动和退出 窗口标题和提示符 命令行颜色 更改编码 启动和退出 按下win R 调出运行窗口 输入cmd就可以进入命令行了 在Win10以前的系统种 如果在命令行中再输入一个cmd 就会再打开一个命令行 但最近的Win11版本中
  • Java解析XML的几种方法

    Java解析XML有几种方法 本文就讨论是怎么使用这四种方法来解析XML文件 并分析他们的优缺点以及应用场合 1 DOM Document Object Model 优点 1 允许应用程序对数据和结构做出更改 2 访问是双向的 可以在任何时
  • 2022年数维杯国际大学生数学建模挑战赛A题自动地震地平线跟踪解题全过程论文及程序

    2022年数维杯国际大学生数学建模挑战赛 A题 自动地震地平线跟踪 原题再现 随着我国经济社会发展 地质工作的重要性也日益提高 地震资料解释是地震勘探工程的一个重要阶段 可以明确油气勘探的地下构造特征 为油气勘探提供良好和有利的储层 准确的
  • spyglass CDC方法学

    CDC issues 亚稳态 spyglass CDC方法学流程 sdc2sgdc 黑盒子的clock用assume path约束 该goal会产生clockreset的约束文件 利用cdc top down也可以从soc顶层生成block
  • IDEA导入eclipse项目并部署tomcat运行Web项目同时配置打WAR包

    工作中点滴记录 本人比较熟悉常用eclipse开发工具 最近在项目中使用eclipse导入同事提供的项目出现文件上传OSS服务失败报找不到桶地址 但使用IDEA打包运行正常 原因未知 迫不得已只能改用IDEA开发 在使用IDEA导入ecli
  • python-Excel多个表格合并

    时间 2019 02 19 工具 python3 7 1 用到的模块 xlrd 负责读取数据 xlsxwriter 负责写入数据 glob 查找符合自己目的的文件 一 模块安装 pip 注意 这里我用的是pip模块来安装 部分python版
  • 算法设计技巧与分析 答案整理

    算法设计技巧与分析 沙特版 这书答案真难找啊 东拼西凑薅出这么些 https wenku baidu com view 279b9245561252d380eb6ea4 html https wenku baidu com view af5
  • 线性分类模型--感知机(perceptron)

    线性分类模型 感知机 perceptron 1 引言 分类问题 分类是监督学习的一个核心问题 在监督学习中 当输出变量Y取有限个离散值时 预测问题便成为分类问题 基本概念可以参考 机器学习方法概论1 监督学习从数据中学习一个分类模型或分类决
  • 蓝桥杯如何混分

    文章目录 蓝桥杯 一 如何暴力求解 二 举例说明 1 蓝桥杯真题 2 暴力代码 3 正解思路 代码 总结 蓝桥杯 蓝桥杯是OI赛制 也就是说即使不会算法 也可以暴力求解 拿到分数 一 如何暴力求解 可以在电脑的编译器上使用超过时间的循环暴力
  • 高等数值计算方法学习笔记第6章【解线性代数方程组的迭代方法(高维稀疏矩阵)】

    高等数值计算方法学习笔记第6章 解线性代数方程组的迭代方法 高维稀疏矩阵 一 引言 1 例题 说明迭代法的收敛性研究的重要性 2 定义 迭代法 迭代法收敛 解误差 二 基本迭代法 1 雅可比迭代法 2 高斯 塞德尔迭代法 Gauss Sei
  • 探究ConcurrentHashMap中键值对在Segment[]的下标如何确定

    内容 本文对JDK1 7下使用segmentShift和segmentMask求解ConcurrentHashMap键值对在Segment 中的下标值进行了探究和论证 适合人群 Java进阶 说明 转载请注明出处 尊重笔者的劳动成果 推荐阅