Java 8: do LongAdder and LongAccumulator AtomicLong prefer?

LongAdder as an alternative to 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 is a more generic version of 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 

I have a few requests.

  • Is LongAdder Preferred For AtomicLong?
  • Is LongAccumulator preferred for both LongAdder and AtomicLong?
+2
source share
2 answers

The distinction between these classes, as well as the use of one over the other, is mentioned in Javadoc. From LongAdder :

This class is usually preferable to AtomicLong , when several threads update the total amount, which is used for statistics purposes, and not for fine-grained timing control. In conditions of low update level, two classes have similar characteristics. But in conditions of high competition, the expected throughput of this class is much higher due to higher space consumption.

And from LongAccumulator :

This class is usually preferable to AtomicLong , when multiple threads update the overall value, which is used for statistics purposes, and not for fine-grained timing control. In conditions of low update level, two classes have similar characteristics. But in conditions of high competition, the expected throughput of this class is much higher due to higher space consumption.

[...]

The LongAdder class provides analogues of the functionality of this class for the general special case of maintaining samples and sums. The call to new LongAdder() equivalent to new LongAccumulator((x, y) -> x + y, 0L) .

Thus, using one over the other depends on what your application intends to do. This is not always strictly preferable only when high concurrency is expected, and you need to maintain a general state.

+3
source

@ Tunaki answered the question expertly, but there is another problem that affects the choice.

To add to a cell, a cell for each stream is required. The internal code uses getProbe () in Striped64, which returns:

returns UNSAFE.getInt (Thread.currentThread (), PROBE);

A probe is a system field used in threadLocalRandomSeed.

I understand that the probe is unique for each thread. If you have a large number of create / destroy threads, then a probe is created for each new thread.

Consequently, the number of cells may become excessive. If anyone has more details about this, I would love to hear from you.

+1
source

Source: https://habr.com/ru/post/1259649/


All Articles