java 8:LongAdder和LongAccumulator是AtomicLong的首选吗?

Rav*_*abu 4 java concurrency java-8

LongAdder 作为替代 AtomicLong

ExecutorService executor = Executors.newFixedThreadPool(2);    
IntStream.range(0, 1000)
    .forEach(i -> executor.submit(adder::increment));    
stop(executor);    
System.out.println(adder.sumThenReset());   // => 1000
Run Code Online (Sandbox Code Playgroud)

LongAccumulator 是一个更通用的版本 LongAdder

LongBinaryOperator op = (x, y) -> 2 * x + y;
LongAccumulator accumulator = new LongAccumulator(op, 1L);

ExecutorService executor = Executors.newFixedThreadPool(2);
IntStream.range(0, 10)
    .forEach(i -> executor.submit(() -> accumulator.accumulate(i)));
stop(executor);

System.out.println(accumulator.getThenReset());     // => 2539
Run Code Online (Sandbox Code Playgroud)

我有一些疑问.

  1. LongAdder总是喜欢AtomicLong的?
  2. 是否LongAccumulator优先选择LongAdder和AtomicLong?

Tun*_*aki 7

Javadoc中提到了这些类之间的差异,以及何时使用其中一个类.来自LongAdder:

AtomicLong当多个线程更新用于收集统计信息但不用于细粒度同步控制的目的的公共和时,此类通常更为可取.在低更新争用下,这两个类具有相似的特征.但在高争用的情况下,这一类的预期吞吐量明显更高,但代价是空间消耗更高.

来自LongAccumulator:

AtomicLong当多个线程更新用于收集统计信息但不用于细粒度同步控制的目的的公共值时,此类通常更为可取.在低更新争用下,这两个类具有相似的特征.但在高争用的情况下,这一类的预期吞吐量明显更高,但代价是空间消耗更高.

[...]

LongAdder提供了此类功能的类比,用于维护计数和总和的常见特殊情况.这个电话new LongAdder()相当于new LongAccumulator((x, y) -> x + y, 0L).

因此,一个使用另一个取决于您的应用程序打算做什么.它并不总是严格优先,只有在预期高并发并且您需要维持一个共同状态时.

  • @ravindra`LongBinaryOperator`?这是一个函数接口,定义了一个以2`long`s为参数并返回`long`的函数方法.因此,它可用于操作2个长度并从某些计算返回长.例如,求和2个long:`LongBinaryOperator longAdder =(x,y) - > x + y;` (2认同)