longaccumulator 是 java 8 提供的灵活并发累加器,支持自定义累积函数(如 max、min、位或等)和初始值,要求函数满足结合律与恒等性;而 longadder 仅支持加法,是其特例。

LongAccumulator 是 Java 8 引入的并发累加器,比 LongAdder 更灵活,因为它支持自定义累积函数(如 max、min、乘积、异或等),而 LongAdder 仅限于加法。它的核心在于用一个二元操作函数(LongBinaryOperator)和初始值来定义累积逻辑。
理解 LongAccumulator 的构造参数
创建 LongAccumulator 需要两个关键参数:
-
累积函数(LongBinaryOperator):接收两个 long 值,返回一个 long 结果。例如
(x, y) -> Math.max(x, y)实现并发求最大值。 -
初始值(identity):当没有更新发生时,
get()返回该值;也作为第一个更新的左操作数(满足恒等性:f(identity, x) == x)。
例如:new LongAccumulator(Math::max, Long.MIN_VALUE) 构建一个线程安全的最大值收集器。
常见灵活场景与对应实现
以下是一些 LongAdder 无法直接支持、但 LongAccumulator 能轻松完成的典型用法:
-
并发求最大值:用
Math::max+Long.MIN_VALUE,各线程调用accumulate(value)更新。 -
并发求最小值:用
Math::min+Long.MAX_VALUE。 -
并发位或(OR)聚合:用
(x, y) -> x | y+0L,适合合并标志位。 -
并发乘积(注意溢出):用
(x, y) -> x * y+1L,适用于小范围数值统计。
与 LongAdder 的关键区别与选择建议
两者底层都基于分段累加(Cell 数组)+ 线程本地缓存,避免竞争,但语义不同:
- LongAdder 是 LongAccumulator 的特例:
new LongAccumulator((x, y) -> x + y, 0L)等价于 new LongAdder()。 - LongAccumulator 要求累积函数满足结合律(f(f(a,b),c) == f(a,f(b,c)))和恒等性(f(identity, x) == x),否则结果不可靠。
- 如果只做加法,优先用 LongAdder —— 语义更清晰、API 更简洁;需要非加法逻辑时,必须选 LongAccumulator。
使用注意事项
实际编码中需留意几个易错点:
- 累积函数必须是无副作用的纯函数,不能修改外部状态或依赖可变变量。
- 初始值必须严格满足恒等性,例如用
Math::max时不能设初始值为 0(若所有输入为负数,结果会错误地变成 0)。 -
getThenReset()返回当前值并重置为 identity,适合周期性指标采集(如每秒请求数),但要注意重置后其他线程的后续 accumulate 仍以 identity 为起点。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











