当前位置: 首页 > news >正文

深入解析 ConcurrentHashMap:从 JDK 1.7 到 JDK 1.8

✨探索Java基础 ConcurrentHashMap✨

引言

ConcurrentHashMap 是 Java 中一个线程安全的高效 Map 集合。它在多线程环境下提供了高性能的数据访问和修改能力。本文将详细探讨 ConcurrentHashMap 在 JDK 1.7 和 JDK 1.8 中的不同实现方式,以及它们各自的优缺点。

基本概念

ConcurrentHashMap 是一个线程安全的哈希表实现,适用于高并发场景。它的设计目标是在保证线程安全的同时,提供尽可能高的性能。

JDK 1.7 版本的 ConcurrentHashMap

接下来看一张图片:

数据结构

在 JDK 1.7 中,ConcurrentHashMap 使用 分段锁(Segment) 的设计。每个 Segment 是一个独立的小哈希表,并且每个 Segment 都有自己的锁。这种设计允许多个线程同时访问不同的 Segment,从而提高并发性能。

  • Segment 数组:默认是 16 个 Segment。
  • HashEntry 数组:每个 Segment 内部有一个 HashEntry 数组,用于存储具体的元素。
  • 链表:如果发生哈希冲突,会使用单向链表来存储冲突的节点。

存储流程

  1. 计算 key 的哈希值:通过 key 的哈希值确定 Segment 数组的下标。
  2. 获取 Segment 锁:对对应的 Segment 进行加锁。
  3. 确定 HashEntry 数组下标:再次通过哈希值确定 HashEntry 数组中的下标。
  4. 存储数据:将数据存入 HashEntry 数组中,如果发生冲突,则挂载到单向链表上。
  5. 附图:

扩容机制

  • 基于 Segment:每个 Segment 维护自己的负载因子,当某个 Segment 中的元素数量超过阈值时,该 Segment 会单独进行扩容。
  • 局部扩容:只影响当前 Segment,不会影响其他 Segment。

size 方法

  • 尝试三次不加锁获取 sum:如果三次总数相同,直接返回;否则,加锁计算总和。

JDK 1.8 版本的 ConcurrentHashMap

看图:

数据结构

在 JDK 1.8 中,ConcurrentHashMap 取消了 Segment 设计,采用了与 HashMap 类似的数据结构:数组 + 链表/红黑树。

  • Node 数组:类似于 HashMap 的数组。
  • 链表/红黑树:当链表长度超过一定阈值时,会转换为红黑树以提高查询效率。

存储流程

  1. 计算 key 的哈希值:通过 key 的哈希值确定 Node 数组的下标。
  2. CAS 添加新节点:使用 CAS 操作尝试添加新节点。
  3. 锁定首节点:如果 CAS 失败或需要更新链表/红黑树,使用 synchronized 锁定首节点。
  4. 存储数据:将数据存入链表或红黑树中。

扩容机制

  • 全局扩容:当整个 ConcurrentHashMap 的元素数量超过阈值时,整个数组会进行扩容。
  • 渐进式扩容:多个线程共同参与扩容操作,逐步迁移旧数据到新数组中,降低扩容时的性能开销。

size 方法

  • 类似 LongAdder 的思想:使用 baseCount 和 counterCells 数组来维护计数。
  • 减少竞争:通过分散计数到多个 counterCell 来减少对单个变量的竞争压力。

代码示例

JDK 1.7 版本

// Segment 类
static final class Segment<K,V> extends ReentrantLock implements Serializable {private final int threshold;transient volatile HashEntry<K,V>[] table;transient int count;transient int modCount;// 构造函数Segment(int initialCapacity, float loadFactor) {this.threshold = (int) (initialCapacity * loadFactor);setTable(HashEntry.<K,V>newArray(initialCapacity));}// put 方法V put(K key, int hash, V value, boolean onlyIfAbsent) {lock(); // 加锁try {int c = count;if (c++ > threshold) // 需要扩容rehash();HashEntry<K,V>[] tab = table;int index = hash & (tab.length - 1);HashEntry<K,V> first = tab[index];HashEntry<K,V> e = first;while (e != null && (e.hash != hash || !key.equals(e.key)))e = e.next;V oldValue;if (e != null) {oldValue = e.value;if (!onlyIfAbsent)e.value = value;} else {oldValue = null;++modCount;tab[index] = new HashEntry<>(key, hash, first, value);}return oldValue;} finally {unlock(); // 解锁}}
}

JDK 1.8 版本

// Node 类
static class Node<K,V> implements Map.Entry<K,V> {final int hash;final K key;volatile V val;volatile Node<K,V> next;Node(int hash, K key, V val, Node<K,V> next) {this.hash = hash;this.key = key;this.val = val;this.next = next;}public final K getKey()       { return key; }public final V getValue()     { return val; }public final String toString() { return key + "=" + val; }
}// putVal 方法
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {Node<K,V>[] tab; Node<K,V> p; int n, i;if ((tab = table) == null || (n = tab.length) == 0)n = (tab = resize()).length;if ((p = tab[i = (n - 1) & hash]) == null)tab[i] = newNode(hash, key, value, null);else {Node<K,V> e; K k;if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))e = p;else if (p instanceof TreeNode)e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);else {for (int binCount = 0; ; ++binCount) {if ((e = p.next) == null) {p.next = newNode(hash, key, value, null);if (binCount >= TREEIFY_THRESHOLD - 1) // 转换为红黑树treeifyBin(tab, hash);break;}if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}}if (e != null) { // 存在键冲突V oldValue = e.val;if (!onlyIfAbsent || oldValue == null)e.val = value;afterNodeAccess(e);return oldValue;}}++modCount;if (++size > threshold)resize();afterNodeInsertion(evict);return null;
}

总结

  • JDK 1.7:使用分段锁(Segment)和 ReentrantLock,每个 Segment 是一个独立的小哈希表,适合中等并发场景。
  • JDK 1.8:采用 CAS 操作和 synchronized 锁定链表或红黑树的首节点,提供了更细粒度的锁,适合高并发场景。

通过这些改进,JDK 1.8 版本的 ConcurrentHashMap 在性能和并发控制方面有了显著的提升。

觉得有用的话可以点点赞 (*/ω\*),支持一下。

如果愿意的话关注一下。会对你有更多的帮助。

每天都会不定时更新哦  >人<  。

相关文章:

深入解析 ConcurrentHashMap:从 JDK 1.7 到 JDK 1.8

✨探索Java基础 ConcurrentHashMap✨ 引言 ConcurrentHashMap 是 Java 中一个线程安全的高效 Map 集合。它在多线程环境下提供了高性能的数据访问和修改能力。本文将详细探讨 ConcurrentHashMap 在 JDK 1.7 和 JDK 1.8 中的不同实现方式&#xff0c;以及它们各自的优缺点。 …...

VS code user setting 与 workspace setting 的区别

VS code user setting 与 workspace setting 的区别 引言正文引言 相信有不少开始接触 VS code 的小伙伴会有疑问,user setting 与 workspace setting 有什么区别呢?这里我们来说明一下 正文 首先,当我们使用 Ctrl + Shift + P 打开搜索输入 setting 后,可以弹出 4 个se…...

XPath基础知识点讲解——用于在XML中查找信息的语言

1. 什么是XPath&#xff1f; XPath&#xff08;XML Path Language&#xff09;是用于在XML&#xff08;Extensible Markup Language&#xff09;文档中查找信息的语言。它可以通过路径表达式来选择XML文档中的节点&#xff0c;类似于如何在文件系统中使用路径查找文件。XPath是…...

Visual Studio 2022

VS&#xff08;Visual Studio&#xff09;是一款由微软开发的集成开发环境&#xff08;IDE&#xff09;&#xff0c;用于开发应用程序、网站以及移动应用等。VS的历史可以追溯到1997年&#xff0c;当时发布了第一个版本的VS。以下是VS的一些重要历史里程碑&#xff1a; Visual …...

微软Win11 22H2/23H2 九月可选更新KB5043145发布!

系统之家于9月27日发出最新报道&#xff0c;微软针对Windows11系统&#xff0c;发布了九月最新可选更新补丁KB5043145&#xff0c;22H2用户安装后&#xff0c;系统版本号升至22621.4249&#xff0c;23H2用户安装后升至22631.4249。本次更新修复了Edge使用IE模式有时会停止响应等…...

试试号称最好的7B模型(论文复现)

试试号称最好的7B模型&#xff08;论文复现&#xff09; 本文所涉及所有资源均在传知代码平台可获取 文章目录 试试号称最好的7B模型&#xff08;论文复现&#xff09;概述论文原理部署与复现推理微调adapter 融合 概述 Mistral 7B 是一个新型的具有 7.3 万亿参数的大语言模型。…...

CTF中文件包含

php伪协议的分类 伪协议是文件包含的基础&#xff0c;理解伪协议的原理才能更好的利用文件包含漏洞。 php://input php://input代表可以访问请求的原始数据&#xff0c;简单来说POST请求的情况下&#xff0c;php://input可以获取到post的数据。 使用条件&#xff1a;includ…...

20.指针相关知识点1

指针相关知识点1 1.定义一个指针变量指向数组2.指针偏移遍历数组3.指针偏移的补充4.指针和数组名的见怪不怪5.函数、指针、数组的结合 1.定义一个指针变量指向数组 指向数组首元素的地址 指向数组起始位置&#xff1a;等于数组名 #include <stdio.h>int main(){int ar…...

PFC和LLC的本质和为什么要用PFC和LLC电路原因

我们可以用电感和电容的特性,以及电压和电流之间的不同步原理来解释PFC(功率因数校正)和LLC(谐振变换器)。 电感和电容的基本概念 电感(Inductor): 电感是一种储存电能的组件。它的电流变化比较慢,电流在电感中延迟,而电压变化得比较快。可以把电感想象成一个“滞后…...

自定义认证过滤器和自定义授权过滤器

目录 通过数据库动态加载用户信息 具体实现步骤 一.创建数据库 二.编写secutity配置类 三.编写controller 四.编写服务类实现UserDetailsService接口类 五.debug springboot启动类 认证过滤器 SpringSecurity内置认证流程 自定义认证流程 第一步:自定义一个类继承Abstr…...

单节点集群的设置及数据写入

背景:elasticsearch单个node节点写入数据-CSDN博客 单个节点数据,如下设置参数, 在单节点集群中,设置 `gateway.recover_after_nodes` 通常是没有意义的,因为单节点集群只有一个节点,无法满足 `gateway.recover_after_nodes` 的条件。然而,如果你仍然想在单节点集群中…...

【Linux学习】【Ubuntu入门】1-2 新建虚拟机ubuntu环境

1.双击打开VMware软件&#xff0c;点击“创建新的虚拟机”&#xff0c;在弹出的中选择“自定义&#xff08;高级&#xff09;” 2.点击下一步&#xff0c;自动识别ubuntu光盘映像文件&#xff0c;也可以点击“浏览”手动选择&#xff0c;点击下一步 3.设置名称及密码后&#xf…...

自动驾驶系列—自动驾驶MCU架构全方位解析:从单核到多核的选型指南与应用实例

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…...

基于单片机多功能称重系统设计

** 文章目录 前言概要功能设计设计思路 软件设计效果图 程序文章目录 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师&#xff0c;一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对…...

PWA(Progressive web APPs,渐进式 Web 应用): manifest.json、 Service Worker

文章目录 引言I 什么是 PWA功能特性技术上分为三个部分安装应用II Web 应用清单将Web 应用清单文件链接到站点manifest.json字段说明III Service Worker( 缓存管理)IV 结合构建工具让项目支持 PWA应用使用插件vite-plugin-pwaworkbox-webpack-plugin插件扩展知识将 PWA 作为脱机…...

【学习笔记】手写 Tomcat 八

目录 一、NIO 1. 创建 Tomcat NIO 类 2. 启动 Tomcat 3. 测试 二、解析请求信息 三、响应数据 创建响应类 修改调用的响应类 四、完整代码 五、测试 六、总结 七、获取全部用户的功能 POJO 生成 POJO 1. 在 Dao 层定义接口 2. 获取用户数据 3. 在 Service 层定…...

24年九月份生活随笔

九月份最后一天&#xff0c;烈士纪念日。 上午看了一会儿直播&#xff0c;庄重的仪式&#xff0c;铭记先辈为新中国抛头颅洒热血&#xff0c;当今盛世&#xff0c;如您所愿。 郑州马拉松官方通告&#xff0c;今天十点公布直通&#xff0c;中签&#xff0c;候补结果。 看完直…...

[含文档+PPT+源码等]精品大数据项目-基于Django实现的高校图书馆智能推送系统的设计与实现

大数据项目——基于Django实现的高校图书馆智能推送系统的设计与实现背景&#xff0c;可以从以下几个方面进行详细阐述&#xff1a; 一、信息技术的发展背景 随着信息技术的飞速发展和互联网的广泛普及&#xff0c;大数据已经成为现代社会的重要资源。在大数据背景下&#xf…...

Leecode刷题之路第七天之整数反转

题目出处 07-整数反转 题目描述 个人解法 思路&#xff1a; 1.将整数转换为字符串 2.倒序输出字符串 3.兼容负数case 代码示例&#xff1a;&#xff08;Java&#xff09; public int reverse(int x) {Integer integer new Integer(x);String s integer.toString();Strin…...

SpringBoot项目 | 瑞吉外卖 | 短信发送验证码功能改为免费的邮箱发送验证码功能 | 代码实现

0.前情提要 之前的po已经说了单独的邮箱验证码发送功能怎么实现&#xff1a; https://blog.csdn.net/qq_61551948/article/details/142641495 这篇说下如何把该功能整合到瑞吉项目里面&#xff0c;也就是把原先项目里的短信发送验证码的功能改掉&#xff0c;改为邮箱发送验证…...

Windows暂停更新

目录 前言注册表设定参考 前言 不想Windows自动更新&#xff0c;同时不想造成Windows商店不可用&#xff0c;可以采用暂停更新的方案。 但是通过这里设定的时间太短了&#xff0c;所以我们去注册表设定。 注册表设定 win r 输入 regedit进入注册表 HKEY_LOCAL_MACHINE\SOFT…...

alpine安装docker踩坑记

文章目录 前言错误场景正确操作最后 前言 你好&#xff0c;我是醉墨居士&#xff0c;最近使用alpine操作系统上docker遇到了一些错误&#xff0c;尝试解决之后就准备输出一篇博客&#xff0c;帮助有需要的后人能够少踩坑&#xff0c;因为淋过雨所以想给别人撑伞 错误场景 我…...

使用openpyxl轻松操控Excel文件

目录 1. openpyxl 简介2. 安装与快速入门2.1 安装 openpyxl2.2 快速创建一个 Excel 文件2.3 读取 Excel 文件 3. openpyxl 的核心概念3.1 工作簿&#xff08;Workbook&#xff09;3.2 工作表&#xff08;Worksheet&#xff09;3.3 单元格&#xff08;Cell&#xff09;3.4 行与列…...

指定PDF或图片多个识别区域,识别区域文字,并批量对PDF或图片文件改名

常见场景 用户有大量图片/PDF文件&#xff0c;期望能按照图片/PDF中的某些文字对图片/PDF文件重命名。期望工具可以批量处理、离线识别&#xff08;保证数据安全性&#xff09;。手工操作麻烦。具体场景&#xff1a;用户有工程现场照片&#xff0c;订单&#xff0c;简历等PDF或…...

Web3中的跨链技术:实现无缝连接的挑战

Web3的到来为互联网带来了去中心化的愿景&#xff0c;而跨链技术则是实现这一愿景的关键。跨链技术旨在解决不同区块链之间的互操作性问题&#xff0c;使得用户和应用能够在多个区块链网络之间无缝地传输数据和价值。尽管这一技术具有广阔的前景&#xff0c;但在实现过程中仍面…...

词袋(Bag of Words, BoW)

词袋&#xff08;Bag of Words, BoW&#xff09;模型详解 词袋&#xff08;BoW&#xff09;是一种用于文本处理的特征提取方法&#xff0c;常用于自然语言处理&#xff08;NLP&#xff09;任务中。在BoW模型中&#xff0c;文本被表示为一个词的无序集合&#xff0c;而忽略了词…...

HTTP Status 404 - /brand-demo/selectAllServlet错误解决原因-Servlet/JavaWeb/IDEA

检查xml文件的包名有无错误检查html文件的url有无写错&#xff0c;是否与Servlet的urlPatterns一致检查Servlet的urlpattern有没有写错(如写成name),检查doPost、doGet是否正常运行 注&#xff1a;IDEA新建Servlet时&#xff0c;默认的WebServlet注解中name需要改urlPatterns&…...

宁夏众智科技OA办公系统存在SQL注入漏洞

漏洞描述 宁夏众智科技OA办公系统存在SQL注入漏洞 漏洞复现 POC POST /Account/Login?ACTIndex&CLRHome HTTP/1.1 Host: Content-Length: 45 Cache-Control: max-age0 Origin: http://39.105.48.206 Content-Type: application/x-www-form-urlencoded Upgrade-Insecur…...

Spring邮件发送:配置与发送邮件详细步骤?

Spring邮件发送教程指南&#xff1f;怎么用Spring邮件发送服务&#xff1f; Spring框架提供了强大的邮件发送支持&#xff0c;使得开发者能够轻松地在应用程序中集成邮件发送功能。AokSend将详细介绍如何在Spring应用中配置和发送邮件&#xff0c;帮助开发者快速掌握这一关键技…...

iPhone/iPad技巧:如何解锁锁定的 iPhone 或 iPad

“在我更新 iPhone 上的软件后&#xff0c;最近我遇到了iPhone 被锁定到所有者的消息&#xff0c;该如何解决&#xff1f;” 根据我们的研究&#xff0c;许多用户在 iOS 18 更新或恢复出厂设置后都会遇到同样的问题。只要出现问题&#xff0c;您就无法使用 iPhone 或 第 1 部分…...

wordpress清理/网站主页

1、打开终端&#xff1b; 2、输入"IDLE3" 转载于:https://www.cnblogs.com/wus0ng/p/10353430.html...

手机建设银行网站进不去/免费发布产品信息的网站

Java语言基本语法 一、标识符和关键字 标识符 在java语言中&#xff0c;用来标志类名、对象名、变量名、方法名、类型名、数组名、包名的有效字符序列&#xff0c;称为“标识符”&#xff1b;标识符由字母、数字、下划线、美元符号组成&#xff0c;且第一个字符不能是数字&…...

哪些做图形推理的网站/图片识别

http://www.redbooks.ibm.com/portals/tivoli...

北京设计网站的公司哪家好/南宁百度seo排名公司

文章目录outfile和dumpfile写shell利用条件基于union联合查询&#xff1a;非联合查询outfile和dumpfile的区别secure_file_prive日志getshell慢日志getshell利用general_logbinlog的介绍outfile和dumpfile写shell 利用条件 数据库当前用户为root权限&#xff1b;知道当前网站的…...

4线城市搞网站开发/百度商城官网

一、前言&#xff1a;mysql8之后想比起之前常用的版本改动还是挺大的&#xff0c;因为刚从安装接触&#xff0c;就先从基本的说起。现在的mysql8安装只能采用解压配置版&#xff0c;像以前老版本的傻瓜式安装将不复存在。其实mysql8了解如何安装之后也不是特别麻烦&#xff0c;…...

wordpress改图片地址/seo网站优化方

ILI9341-TFT LCD驱动(基于TFT_eSPI库) 液晶显示器 (LCD) 是一种平板显示器或其他电子调制光学设备,它利用液晶与偏振器的光调制特性。液晶不直接发光,而是使用背光或反射器来产生彩色或单色图像。LCD 可用于显示任意图像(如在通用计算机显示器中)或具有低信息内容的固定…...