LongAdder 类是 LongAccumulator 的一个特例,LongAccumulator 比 LongAdder 的功能更强大。例如下面的构造函数,其中 accumulatorFunction 是一个双目运算器接口,其根据输入的两个参数返回一个计算值,identity 则是 LongAccumulator 累加器的初始值。

    1. public LongAccumulatorLongBinaryOperator accumulatorFunction,
    2. long identity {
    3. this.function = accumulatorFunction
    4. base = this.identity = identity
    5. }
    6. public interface LongBinaryOperator {
    7. //根据两个参数计算并返回一个值
    8. long applyAsLonglong left, long right);
    9. }

    上面提到,LongAdder 其实是 LongAccumulator 的一个特例,调用 LongAdder 就相当于使用下面的方式调用 LongAccumulator:

    1. LongAdder adder = new LongAdder();
    2. LongAccumulator accumulator = new LongAccumulator(new LongBinaryOperator() {
    3. @Override
    4. public long applyAsLong(long left, long right) {
    5. return left + right;
    6. }
    7. }, 0);

    LongAccumulator 相比于 LongAdder,可以为累加器提供非 0 的初始值,后者只能提供默认的 0 值。另外,前者还可以指定累加规则,比如不进行累加而进行相乘,只需要在构造 LongAccumulator 时传入自定义的双目运算器即可,后者则内置累加的规则。

    从下面代码我们可以知道,LongAccumulator 相比于 LongAdder 的不同在于,在调用 casBase 时后者传递的是 b+x,前者则使用了 r = function.applyAsLong(b = base, x)来计算。

    1. //LongAdder 的 add
    2. public void addlong x {
    3. Cell[] as long b v int m Cell a
    4. if ((as = cells) ! = null || ! casBase(b = base, b + x)) {
    5. boolean uncontended = true
    6. if as == null || (m = as.length -1) < 0 ||
    7. (a = as[getProbe() & m]) == null ||
    8. !(uncontended = a.cas(v = a.value, v + x)))
    9. longAccumulatex, null, uncontended);
    10. }
    11. }
    12. //LongAccumulator 的 accumulate
    13. public void accumulatelong x {
    14. Cell[] as long b v r int m Cell a
    15. if ((as = cells) ! = null ||
    16. (r = function.applyAsLong(b = base, x)) ! = b && ! casBase(b, r)) {
    17. boolean uncontended = true
    18. if as == null || (m = as.length -1) < 0 ||
    19. (a = as[getProbe() & m]) == null ||
    20. !(uncontended =
    21. (r = function.applyAsLong(v = a.value, x)) == v ||
    22. a.cas(v, r)))
    23. longAccumulatex, function, uncontended);
    24. }
    25. }

    另外,前者在调用 longAccumulate 时传递的是 function,而后者是 null。从下面的代码可知,当 fn 为 null 时就使用 v+x 加法运算,这时候就等价于 LongAdder,当 fn 不为 null 时则使用传递的 fn 函数计算。

    1. else if (casBase(v = base, ((fn == null) ? v + x :
    2. fn.applyAsLong(v, x))))
    3. break; // Fall back on using base

    总结:本节简单介绍了 LongAccumulator 的原理。LongAdder 类是 LongAccumulator 的一个特例,只是后者提供了更加强大的功能,可以让用户自定义累加规则。