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
我有一些疑问。
- Is
LongAdder
总是优先于 AtomicLong?
- 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(使用前将#替换为@)