讲师中心 微信公众号
AI工具推荐 视频效率加速

如何在集合框架中处理并发计数_Map与LongAdder的高效组合

小宇吖_1404

小宇吖_1404

发布时间:2026-02-20 13:37:02

|

479人浏览过

|

来源于php中文网

原创

ConcurrentHashMap + LongAdder 更快是因为LongAdder将累加分散到多个cell,避免高并发下的CAS重试竞争;而ConcurrentHashMap的compute/merge仍存在锁或CAS冲突,尤其在万级TPS时CPU大量耗在重试上。

如何在集合框架中处理并发计数_map与longadder的高效组合

为什么 ConcurrentHashMap + LongAdder 比直接用 ConcurrentHashMap<long></long> 更快

因为 ConcurrentHashMap 的 compute 或 merge 方法在高并发下仍会触发锁竞争(哪怕只是分段锁或 CAS 重试),而 LongAdder 把计数分散到多个单元,写操作几乎无冲突。你不是在“更新一个值”,而是在“往不同槽里加一”,最后才汇总——这对高频累加场景就是质变。

常见错误现象:ConcurrentHashMap.compute(key, (k, v) -> v == null ? 1L : v + 1) 在万级 TPS 下 CPU 花费大量时间在 CAS 失败重试上,LongAdder.sum() 却稳定低开销。

  • 适用场景:统计请求量、缓存命中次数、接口调用量等纯累加型指标
  • 不适用场景:需要原子读-改-写(比如“如果小于阈值才加”)、或要求严格实时一致性的计数
  • LongAdder 不是线程安全的“变量替代品”,它不能直接当 long 用;必须用 sum() 或 longValue() 获取当前值

怎么把 LongAdder 存进 ConcurrentHashMap 并避免内存泄漏

不能直接 new 一个 LongAdder 放进去就完事——如果 key 长期不访问,对应 LongAdder 实例会一直占着内存,且 ConcurrentHashMap 不会自动清理未使用的计数器。

正确做法是结合 computeIfAbsent 按需创建,并配合弱引用或定期清理逻辑(视业务周期而定):

Map<String, LongAdder> counters = new ConcurrentHashMap<>();
// 安全获取并累加
counters.computeIfAbsent("api/login", k -> new LongAdder()).increment();
  • 每次 computeIfAbsent 都是无锁路径,只有首次 put 时才可能有轻微竞争
  • 不要用 getOrDefault(key, new LongAdder()) —— 这会每次新建实例,造成对象爆炸和 GC 压力
  • 如果 key 有明确生命周期(如用户 session ID),建议搭配 ScheduledExecutorService 定期扫描过期 key 并 remove

ConcurrentHashMap 的遍历与快照一致性问题

ConcurrentHashMap 迭代器是弱一致的,遍历时其他线程仍在写 LongAdder,所以你拿到的 sum() 只是那一刻的近似值——这不是 bug,是设计使然。

如果你需要“某一时刻所有计数器的总和”,不能边遍历边加,而要先收集所有 LongAdder 引用,再统一调用 sum():

List<LongAdder> adders = new ArrayList<>(counters.values());
long total = adders.stream().mapToLong(LongAdder::sum).sum();
  • 避免在遍历 entrySet() 时直接调用 getValue().sum() —— 中间可能被其他线程修改,结果不可重现
  • LongAdder.sum() 是非阻塞的,但多次调用之间没有顺序保证;一次收集 + 一次批量 sum 才接近“快照”语义
  • 如果对一致性要求极高(比如计费场景),这种组合就不适合;该换 StampedLock + long[] 或专用指标库(如 Micrometer)

LongAdder 和 AtomicLong 在什么情况下反而更慢

当并发度极低(比如单线程反复调用),LongAdder 的内部 cell 分配、跳转、分支预测开销反而比 AtomicLong 的单 CAS 更重。

  • 实测显示:QPS AtomicLong.incrementAndGet() 通常快 10%–20%
  • LongAdder 的优势从几百次/秒写操作开始显现,在数千以上才真正拉开差距
  • 别为了“看起来高级”强行替换;压测你的实际负载路径,看 ThreadMXBean.getThreadCpuTime() 或 Arthas trace 结果

最易被忽略的一点:LongAdder 的内存占用是 AtomicLong 的数倍(默认最多 128 个 cell),小堆或大量 key 场景下容易推高 GC 频率——不是所有“高效”都只看吞吐。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

小橡皮AI

一款AI工具,主要用于小橡皮一键去AI味,将机器味重的内容改得更有活人感,防止因为 AI 内容被平台打上 AI 标签,以及限流,适合需要提升相关任务效率的用户。

Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

Seko
Seko Hot

一款AI视频创作工具,主要用于商汤科技推出的创编一体的AI短视频创作Agent,适合需要提升相关任务效率的用户。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

6759

2023.08.02

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

549

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1698

2024.03.01

session失效的原因
session失效的原因

session失效的原因有会话超时、会话数量限制、会话完整性检查、服务器重启、浏览器或设备问题等等。详细介绍:1、会话超时:服务器为Session设置了一个默认的超时时间,当用户在一段时间内没有与服务器交互时,Session将自动失效;2、会话数量限制:服务器为每个用户的Session数量设置了一个限制,当用户创建的Session数量超过这个限制时,最新的会覆盖最早的等等。

580

2023.10.17

session失效解决方法
session失效解决方法

session失效通常是由于 session 的生存时间过期或者服务器关闭导致的。其解决办法:1、延长session的生存时间;2、使用持久化存储;3、使用cookie;4、异步更新session;5、使用会话管理中间件。

876

2023.10.18

cookie与session的区别
cookie与session的区别

本专题整合了cookie与session的区别和使用方法等相关内容,阅读专题下面的文章了解更详细的内容。

1926

2025.08.19

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

3188

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

5089

2025.10.17

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

20

2026.10.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn