一、 LongAccumulator類原理探究
LongAdder類是LongAccumulator的一個(gè)特例,LongAccumulator提供了比LongAdder更強(qiáng)大的功能,如下構(gòu)造函數(shù)其中accumulatorFunction一個(gè)雙目運(yùn)算器接口,根據(jù)輸入的兩個(gè)參數(shù)返回一個(gè)計(jì)算值,identity則是LongAccumulator累加器的初始值啸澡。
public LongAccumulator(LongBinaryOperator accumulatorFunction,
long identity) {
this.function = accumulatorFunction;
base = this.identity = identity;
}
public interface LongBinaryOperator {
//根據(jù)兩個(gè)參數(shù)計(jì)算返回一個(gè)值
long applyAsLong(long left, long right);
}
LongAdder其實(shí)是LongAccumulator的一個(gè)特例袖订,調(diào)用LongAdder相當(dāng)使用下面的方式調(diào)用LongAccumulator。
LongAdder adder = new LongAdder();
LongAccumulator accumulator = new LongAccumulator(new LongBinaryOperator() {
@Override
public long applyAsLong(long left, long right) {
return left + right;
}
}, 0);
LongAccumulator相比于LongAdder可以提供累加器初始非0值嗅虏,后者只能默認(rèn)為0洛姑,另外前者還可以指定累加規(guī)則比如不是累加而是相乘,只需要構(gòu)造LongAccumulator時(shí)候傳入自定義雙面運(yùn)算器就OK皮服,后者則內(nèi)置累加的規(guī)則楞艾。
從下面代碼知道LongAccumulator相比于LongAdder不同在于casBase時(shí)候后者傳遞的是b+x,前者則是調(diào)用了r = function.applyAsLong(b = base, x)來計(jì)算。
public void add(long x) {
Cell[] as; long b, v; int m; Cell a;
if ((as = cells) != null || !casBase(b = base, b + x)) {
boolean uncontended = true;
if (as == null || (m = as.length - 1) < 0 ||
(a = as[getProbe() & m]) == null ||
!(uncontended = a.cas(v = a.value, v + x)))
longAccumulate(x, null, uncontended);
}
}
public void accumulate(long x) {
Cell[] as; long b, v, r; int m; Cell a;
if ((as = cells) != null ||
(r = function.applyAsLong(b = base, x)) != b && !casBase(b, r)) {
boolean uncontended = true;
if (as == null || (m = as.length - 1) < 0 ||
(a = as[getProbe() & m]) == null ||
!(uncontended =
(r = function.applyAsLong(v = a.value, x)) == v ||
a.cas(v, r)))
longAccumulate(x, function, uncontended);
}
}
另外前者調(diào)用longAccumulate時(shí)候傳遞到是function,而后者是null龄广,從下面代碼可知當(dāng)fn為null時(shí)候就是使用v+x加法運(yùn)算這時(shí)候就等價(jià)于LongAdder硫眯,fn不為null時(shí)候則使用傳遞的fn函數(shù)計(jì)算,如果fn為加法則等價(jià)于LongAdder择同;
else if (casBase(v = base, ((fn == null) ? v + x :
fn.applyAsLong(v, x))))
break; // Fall back on using base
更詳細(xì)的說明敬請期待 Java并發(fā)編程基礎(chǔ)之并發(fā)包源碼剖析 一書的出版