java 8:LongAdder 和 LongAccumulator 是否优于 AtomicLong?

2023-12-28

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

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

我有一些疑问。

  1. Is LongAdder总是优先于 AtomicLong?
  2. Is LongAccumulator优于 LongAdder 和 AtomicLong?

Javadoc 中提到了这些类之间的区别以及何时使用其中一个类。从LongAdder https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/LongAdder.html:

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

并从LongAccumulator https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/LongAccumulator.html:

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

[...]

Class LongAdder为维护计数和总和的常见特殊情况提供此类的功能类似物。电话new LongAdder()相当于new LongAccumulator((x, y) -> x + y, 0L).

因此,使用其中一种取决于您的应用程序打算做什么。它并不总是严格首选,只有当预计高并发性并且需要维护公共状态时。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java 8:LongAdder 和 LongAccumulator 是否优于 AtomicLong? 的相关文章

随机推荐