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

ConcurrentHashMap的putIfAbsent方法详解与应用_元一软件

在并发编程中,ConcurrentHashMap是一个常用的线程安全哈希表实现,它提供了多种原子操作方法来简化并发环境下的数据更新。其中,putIfAbsent方法是一个简单而强大的工具,用于在键不存在时插入值,键存在时则不执行任何操作。本文将详细解析putIfAbsent方法的作用、用法、源码逻辑以及与其他相关方法的对比。


putIfAbsent方法的作用

putIfAbsent方法用于在键不存在时原子性地插入值,键存在时则不执行任何操作。这对于需要避免重复插入或初始化的场景非常有用。

方法定义

V putIfAbsent(K key, V value)

核心特性

典型使用场景

简单缓存系统

ConcurrentHashMap<String, Config>configCache=new ConcurrentHashMap<>();public Config getConfig(String configName){Config config=new Config(configName);// 可能创建多余对象 Config existing=configCache.putIfAbsent(configName, config);returnexisting!=null ? existing:config;}

避免重复初始化

ConcurrentHashMap<String, List<String>>listCache=new ConcurrentHashMap<>();public List<String>getList(String key){List<String>list=new ArrayList<>();List<String>existing=listCache.putIfAbsent(key, list);returnexisting!=null ? existing:list;}

源码逻辑简化

final V putIfAbsent(K key, V value){if(key==null||value==null)throw new NullPointerException();inthash=spread(key.hashCode());for(Node<K,V>[]tab=table;;){Node<K,V>f;int n, i, fh;if(tab==null||(n=tab.length)==0)tab=initTable();elseif((f=tabAt(tab,i=(n-1)&hash))==null){// 键不存在,尝试插入新节点if(casTabAt(tab, i, null, new Node<K,V>(hash, key, value, null)))break;}elseif((fh=f.hash)==MOVED)tab=helpTransfer(tab,f);//协助扩容 else { V oldVal=null;synchronized(f){//锁住当前桶的头节点 if(tabAt(tab,i)==f){//遍历链表或红黑树查找键 for(Node<K,V>e=f;;){ if(e.hash==hash&&((ek=e.key)==key||key.equals(ek))){oldVal=e.val;break;}if((e=e.next)==null)break;}if(oldVal==null){// 键不存在,插入新节点 addNode(tab, hash, key, value, i);}}}if(oldVal!=null)returnoldVal;}}addCount(1L, binCount);returnnull;}

与computeIfAbsent对比

特性putIfAbsentcomputeIfAbsent
触发条件键不存在键不存在或值为null
值创建时机调用前创建(可能多余)函数内按需创建
函数参数Function<K, V>
适用场景对象创建成本低、简单插入延迟初始化、复杂对象创建

最佳实践

完整示例

importjava.util.concurrent.ConcurrentHashMap;public class PutIfAbsentDemo{public static void main(String[]args){ConcurrentHashMap<String, Integer>cache=new ConcurrentHashMap<>();// 插入键值对(键不存在) Integer oldValue=cache.putIfAbsent("a",1);System.out.println("Old value for 'a': "+ oldValue);// 输出: null // 尝试插入已存在的键 oldValue=cache.putIfAbsent("a",2);System.out.println("Old value for 'a': "+ oldValue);// 输出:1System.out.println("Current value for 'a': "+ cache.get("a"));// 输出:1}}
http://www.gsyq.cn/news/1621858.html

相关文章:

  • GPU并行计算架构与性能优化实战指南
  • 终极Windows任务栏监控神器:TrafficMonitor插件完全指南
  • STM32嵌入式开发终极指南:从零构建智能温控系统
  • 暗黑破坏神2存档编辑器技术解析:基于MPQ数据解析的Web可视化编辑方案
  • paperxie AI 科研绘图:一站式科研出图工具,告别 Origin 与 Visio 繁琐制图
  • 2026年横评:16款降AIGC工具横评,这款降AI率效果一骑绝尘!
  • CM/Ethyl/HP-HA,HA-Glycyrrhetinic acid,甘草次酸修饰透明质酸的特点
  • 2026年选空间设计公司,这3家专业度拉满
  • IMU传感器与MCU实现6DoF运动追踪技术解析
  • PIC18F4685驱动WS2812B LED的嵌入式开发实践
  • CBCX外汇在风险提示上会不会更省事?
  • KMX62与PIC18F4610在工业稳定控制中的创新应用
  • 无刷直流电机驱动系统设计与优化实践
  • ASM330LHH与STM32F413运动跟踪系统开发指南
  • 高效多任务观看视频:Google官方画中画浏览器插件完全指南
  • 基于WSEN-ISDS和PIC32的三维运动跟踪系统实现
  • 15A高功率FOC无刷电机控制方案设计与优化
  • 如何5分钟破解Ren‘Py游戏资源?unrpa让你成为专业级提取专家
  • CBCX外汇在风险提示上顺手吗?
  • 宜春口腔机构甄选攻略:从设备、医生、服务多维避坑
  • 从3D到6DoF:IMU传感器与PIC微控制器的运动追踪方案
  • 终极游戏库管理指南:如何用Playnite一站式管理所有平台游戏 [特殊字符]
  • STM32与TC78H660FTG直流电机驱动方案详解
  • 静音直流电机控制方案与TB9051FTG应用实践
  • 模板驱动文档自动化:从填空题到文档工厂的工程化实践
  • JMeter实战:深入解析文件导入导出接口性能测试原理与方案
  • ICM-42688-P与STM32F302VC在运动感知系统中的应用
  • 22寸行李箱推荐:2026适配全出行场景高性价比拉杆箱测
  • Playnite便携版架构深度解析:跨平台游戏管理的技术实现
  • 工业智能温度显示系统设计与动态阈值算法实践