doubleadder是专为double类型设计的高并发累加器,不支持float;其通过base+cell分段机制提升吞吐,但sum()返回近似快照且存在浮点精度丢失,适用于监控等精度不敏感场景。

Java 中没有 DoubleAdder 的浮点数专用版本,DoubleAdder 本质是为 double 类型设计的高性能累加器,但它底层不直接支持浮点数的原子累加(如 float),也不提供 float 版本。所以“用 DoubleAdder 处理高并发浮点数累加”这个说法需先明确:你指的是 double 还是 float?如果是 float,不能直接用 DoubleAdder;如果是 double,它正是为此场景优化的。
DoubleAdder 是专为 double 累加设计的无锁高性能工具
DoubleAdder 是 Java 8 引入的 java.util.concurrent.atomic 包中的类,用于在高并发下高效累加 double 值。它通过分段累加(cell 分片)+ 主值合并的策略,避免了 AtomicDouble(不存在)或 synchronized + Double 对象带来的竞争瓶颈。
- 内部维护一个 base 值和一组 Cell 数组,线程优先尝试更新自己的 Cell,冲突时才扩容或回退到 base
- 不依赖 CAS 循环重试整个 double 值(double 占 8 字节,JVM 不保证 64 位写天然原子,但
DoubleAdder通过 Unsafe 和内存屏障规避了该问题) - 最终结果用
sum()获取,是近似实时值(非强一致,但对统计类场景完全够用)
正确使用 DoubleAdder 累加 double 值
直接创建、调用 add()、最后取 sum() 即可。注意它不可变、不可重置(Java 9+ 提供了 reset(),但多数老版本需新建实例)。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
DoubleAdder adder = new DoubleAdder(); // 多个线程并发执行 adder.add(3.14159); adder.add(-2.718); adder.add(1.414); double result = adder.sum(); // 例如:1.83759...
- 避免用
doubleValue()或包装类型操作——DoubleAdder不是Double包装器,它不实现Number - 不要在循环中频繁调用
sum()做条件判断(性能开销略高,且非实时),适合汇总阶段一次性读取 - 若需原子读-改-写(如“加完后判断是否超阈值”),
DoubleAdder不支持,应改用AtomicReference<double></double>+ CAS 循环(但性能差很多)
float 类型怎么办?没有 FloatAdder
Java 标准库至今(JDK 21)仍无 FloatAdder。处理高并发 float 累加有几种务实选择:
-
升格为 double:绝大多数场景 float 精度已过剩,直接用
DoubleAdder并传入(double)f,精度无损,语义清晰 -
用 AtomicInteger 模拟 float bit 操作(不推荐):将
float转为intbits(Float.floatToIntBits(f)),再用AtomicInteger累加 int,但加法在 bit 层面无意义,逻辑错误 -
自定义基于 Cell 的 FloatAdder(极少必要):复制
DoubleAdder源码,把double替换为float,并用Float.floatToRawIntBits/Float.intBitsToFloat配合Unsafe,但维护成本高、易出错,仅限极端场景
和替代方案对比:为什么选 DoubleAdder 而不是别的
在吞吐量敏感的统计、监控、计费等场景中,DoubleAdder 明显优于其他方式:
-
synchronized(double total):锁粒度大,并发越高越慢,可能成为瓶颈 -
AtomicReference<double></double>+ CAS 循环:每次都要读-改-写整个对象,存在 ABA 和重试开销,且Double是不可变对象,每次 new 带 GC 压力 -
LongAdder存放放大后的 long(如 ×1000):适用于固定小数位,但会损失精度、增加业务转换负担 -
DoubleAdder:无锁、低竞争、内存友好、API 简洁,是 JDK 官方推荐的 double 累加方案
不复杂但容易忽略:DoubleAdder 不是万能的,它牺牲了强一致性来换取吞吐,适合“最终汇总”类需求;如果你需要严格实时、线性一致的 double 累加(比如金融核心账务),仍需结合锁或分布式事务,而非依赖它。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










