LongAdder作为AtomicLong的替代方案
ExecutorService executor = Executors.newFixedThreadPool(2);
IntStream.range(0, 1000)
.forEach(i -> executor.submit(adder::increment));
stop(executor);
System.out.println(adder.sumThenReset()); // => 1000LongAccumulator是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我有些疑问。
LongAdder总是比AtomicLong更好吗?LongAccumulator比LongAdder和AtomicLong更好吗?发布于 2016-02-28 22:15:19
Javadoc中提到了这些类之间的区别,以及何时使用其中一种而另一种。来自LongAdder
当多个线程更新一个用于收集统计信息,而不是用于细粒度同步控制的公共和时,这个类通常比
AtomicLong更好。在低更新争用条件下,两类具有相似的特性。但是在竞争激烈的情况下,这类的预期吞吐量要高得多,而牺牲了更高的空间消耗。
当多个线程更新一个用于收集统计信息,而不是用于细粒度同步控制的公共值时,这个类通常比
AtomicLong更可取。在低更新争用条件下,两类具有相似的特性。但是在竞争激烈的情况下,这类的预期吞吐量要高得多,而牺牲了更高的空间消耗。 ..。 类LongAdder为维护计数和和的常见特殊情况提供了类似于该类的功能。调用new LongAdder()等同于new LongAccumulator((x, y) -> x + y, 0L)。
因此,使用一个比另一个取决于您的应用程序打算做什么。它并不总是被严格地优先考虑,只有在高并发性被期望时,并且您需要维护一个公共状态时,才会被严格地接受。
发布于 2016-02-28 23:12:12
@Tunaki巧妙地回答了这个问题,但仍然有一个问题影响着选择。
添加到单元格需要每个线程一个单元格。内部代码在getProbe()中使用Striped64,它返回:
返回UNSAFE.getInt(Thread.currentThread(),探测);
探针是threadLocalRandomSeed中的一个系统字段。
我的理解是,每个线程的探测都是独一无二的。如果有大量线程创建/销毁,则为每个新线程创建探测。
因此,细胞数量可能会过多。如果有人对此有更详细的了解,我想听听你的意见。
https://stackoverflow.com/questions/35688862
复制相似问题