2016-02-28 29 views
2

LongAdder作爲替代AtomicLongjava 8:LongAdder和LongAccumulator是AtomicLong的首選嗎?

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

LongAccumulatorLongAdder

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. LongAdder總是首選AtomicLong?
  2. 是否LongAccumulator首選LongAdder和AtomicLong?

回答

3

Javadoc中提到了這些類之間的區別,以及何時使用另一類。從LongAdder

這個類是通常優選AtomicLong當多個線程更新時使用,用於諸如收集統計信息,不用於細粒度同步控制的共同總和。在低更新爭用下,這兩個類別具有相似的特徵。但是,在高度爭論中,該類別的預期吞吐量顯着較高,但以較高的空間消耗爲代價。

而且從LongAccumulator

這個類是通常優選AtomicLong當多個線程更新時使用,用於諸如收集統計信息,不用於細粒度同步控制的公共值。在低更新爭用下,這兩個類別具有相似的特徵。但是,在高度爭論中,該類別的預期吞吐量顯着較高,但以較高的空間消耗爲代價。

[...]

LongAdder提供的這個類的維護計數和資金的共同特例的功能類似物。致電new LongAdder()相當於new LongAccumulator((x, y) -> x + y, 0L)

因此,相互之間的使用取決於您的應用程序打算做什麼。它並不總是被嚴格地優先考慮,只有當預期高併發性並且你需要維持一個共同的狀態時。

+0

現在有所不同。你能解釋一下上面的代碼片段中的二元運算符部分嗎? –

+2

@ravindra'LongBinaryOperator'?這是一個函數接口,定義了一個以2個long參數爲參數並返回一個long參數的函數方法。所以,它可以用來操作2個多頭並從一些計算中返回一個長頭。例如,求和2個長整數:'LongBinaryOperator longAdder =(x,y) - > x + y;' – Tunaki

1

@Tunaki熟練地回答了這個問題,但仍然有一個問題影響選擇。

添加到單元需要每個線程有一個單元。內部代碼在Striped64中使用getProbe()返回:

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

Probe是threadLocalRandomSeed中使用的系統字段。

我的理解是探針對每個線程都是唯一的。如果創建/銷燬的線程數量很多,則爲每個新線程創建探針。

因此,單元的數量可能會變得過多。如果有人對此有更多的細節,我想聽聽你的意見。

+0

看來你已經在錯誤的問題中發佈了你的答案。 –

+0

@ravindra是怎麼回事?問題是關於選擇,我回答了這個問題。 – edharned

+0

明白了。你能否詳細說明這三個類的探索和關係? –