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

ConcurrentHashMap学习

ConcurrentHashMap是 Java 并发编程中极其重要且常用的数据结构。它是线程安全的哈希表实现,专为高并发场景设计,相比全局加锁的Hashtable,它通过更细粒度的锁机制(JDK 1.7 的分段锁,以及 JDK 1.8 之后的 CAS + synchronized)实现了极高的并发读写性能。

以下是ConcurrentHashMap的核心使用指南和最佳实践:

一、 基础使用与初始化

ConcurrentHashMap的基本 API 与HashMap类似,但有几个关键区别需要注意:

  1. 不允许 null:它的 Key 和 Value 都不允许为 null,如果传入会直接抛出NullPointerException
  2. 预设容量:如果在创建时能预估数据规模,建议指定初始容量,这可以有效减少运行过程中的 rehash(扩容)次数,提升性能。
// 1. 默认初始化ConcurrentHashMap<String,Integer>map=newConcurrentHashMap<>();// 2. 指定初始容量(推荐,减少扩容开销)ConcurrentHashMap<String,Integer>mapWithCapacity=newConcurrentHashMap<>(32);

二、 核心原子操作方法(重点)

在多线程环境下,传统的“先检查再更新”(Check-then-Act)操作是不安全的。ConcurrentHashMap提供了一系列原子性的复合操作方法,强烈建议优先使用这些方法来简化代码并保证线程安全:

1. putIfAbsent(key, value)
如果指定的键不存在,才插入键值对。常用于实现简单的缓存或防止重复初始化。

// 只有当 "user_1" 不存在时,才会放入数据map.putIfAbsent("user_1",100);

2. computeIfAbsent(key, mappingFunction)
如果键不存在,则通过传入的函数计算出一个值并放入 Map。这是一个极其优雅的懒加载实现方式,且函数内部只会执行一次。

// 如果 "user_2" 不存在,则计算其分数并放入map.computeIfAbsent("user_2",key->calculateScore(key));

3. compute / merge (高频更新场景)
当需要对已存在的值进行更新时(如计数器),使用这两个方法可以避免多次加锁。

// 优雅地实现单词计数:如果存在则相加,不存在则设为 1map.merge("word",1,Integer::sum);

三、 安全的遍历与状态获取

在并发环境下,普通的size()方法或entrySet遍历可能因为其他线程的修改而变得不准确,甚至抛出异常。ConcurrentHashMap提供了专门的应对机制:

  1. 弱一致性遍历:使用forEachsearchreduce等专用方法进行遍历。这些方法不仅线程安全,而且不会抛出ConcurrentModificationException,但它们反映的可能是某一时刻的近似状态。
  2. 精确获取大小:如果业务强依赖集合的精确大小,应使用mappingCount()方法代替size(),它返回long类型,在并发下更加精确。
// 安全的并发遍历map.forEach((key,value)->{System.out.println(key+": "+value);});// 获取更精确的元素数量longcount=map.mappingCount();

四、 极致性能优化:LongAdder

在诸如“单词计数”、“接口限流统计”等高频更新的场景下,即使使用了ConcurrentHashMap,多线程同时 CAS 更新同一个 Key 对应的值依然会产生竞争。此时,可以将 Value 设为LongAdder来极致优化:

ConcurrentHashMap<String,LongAdder>wordCounts=newConcurrentHashMap<>();// 结合 computeIfAbsent 和 LongAdder 实现无锁化高频累加wordCounts.computeIfAbsent("hello",k->newLongAdder()).increment();

五、 核心注意事项总结

  • 严禁外部加锁:不要使用synchronized(map)来包裹ConcurrentHashMap的操作,这会破坏其内部的细粒度并发优势,使其退化为串行执行。
  • 迭代器是弱一致的:在遍历过程中,如果其他线程修改了 Map,迭代器不会报错,但也不保证能遍历到最新修改的数据。
  • 底层演进:JDK 1.8 之后,它摒弃了 1.7 时代的Segment分段锁,全面采用Node数组 + 链表 + 红黑树结构,结合CAS + synchronized锁住单个桶的头节点,并发度理论上最高可达数组长度。
http://www.jsqmd.com/news/1159414/

相关文章:

  • Gemini Mac原生App:深度集成macOS的AI工作流引擎
  • 现代AI之父新作:13个大模型实测,检索agent真的可信吗?
  • 重复测量方差分析:SPSS 球形度检验(Mauchly‘s W)与3种校正方法(GG/HF/下限)详解
  • 5分钟解锁专业图表制作:drawio-libs图标库完全指南
  • API Key轮换不是改变量:从分环境到撤销演练的证据链
  • AutoHotkey v2 实战:5个脚本实现文本大小写/驼峰转换与窗口置顶
  • 计算机毕业设计之社团纳新管理系统设计与实现
  • 公证在线办理多久办好?公证材料有啥?
  • 技术、业务、管理:一个30岁前端的十字路口
  • Open WebUI 搭配 Ollama 运行 DeepSeek 的本地 GUI 实战指南
  • 2026年7月最新厦门海沧区新阳街道亨得利官方名表服务中心电话公示 - 亨得利钟表维修中心
  • 【推荐一款免费的企业管理软件】
  • Firefox+Burpsuite+SwitchyOmega黄金组合:Web安全测试抓包环境搭建与配置实战
  • 智能体平台有哪些监控仪表盘?企业级AI Agent全链路可视化与合规监控深度解析
  • 便携式自动粘度测定仪:技术参数与场景应用全解析
  • 三相电压型PWM整流器、PI双闭环+解耦、第四象限、电流反向流动仿真(Simulink仿真实现)
  • 第五人格时间计算:加赛、破译加速与闪现时机详解
  • Claude Fable 5免费试用延期:AI编程助手深度评测与实战指南
  • Windows和Linux快速生成大容量文件的完整指南
  • 线上商城SaaS平台哪家最适合中小企业,AI标配能力正在重塑“适合“的定义
  • 毫秒级响应:源网荷储一体化柜如何实现秒级并离网切换?
  • 基于AD590和uA741的温度测量电路设计与Multisim仿真
  • 2026冰块批发Top5测评:贵阳大冰块哪家强?良臣制冰厂封神 - 热点咨讯
  • 鸿蒙新特性:ScrollBar 滚动条定制与文档阅读器实战
  • Qwen2.5-VL 零样本目标检测实战:提示词定位与 自定义数据集测试
  • AIGC前沿技术解析:单步扩散模型、Few-shot NeRF与3D高斯优化
  • 凭借这份Java架构六大核心专题,我半月斩获了8个Offer!
  • Vue 3 + CodeMirror 6 文本对比实战:集成 diff-match-patch 实现 3 种合并策略
  • AI编程助手实战:从Codex原理到DeepSeek API集成配置全指南
  • AI应用公司争议不断:价值几何?能否抵御风浪?