privatefinalLongBinaryOperatorfunction;//操作累加方法
privatefinallongidentity;//初始化base值
/**
* Creates a new instance using the given accumulator function
* and identity element.
* @param accumulatorFunction a side-effect-free function of two arguments
* @param identity identity (initial value) for the accumulator function
*/publicLongAccumulator(LongBinaryOperatoraccumulatorFunction,longidentity){this.function=accumulatorFunction;base=this.identity=identity;}
二、accumulate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* Updates with the given value.
*
* @param x the value
*/publicvoidaccumulate(longx){Cell[]as;longb,v,r;intm;Cella;if((as=cells)!=null||(r=function.applyAsLong(b=base,x))!=b&&!casBase(b,r)){booleanuncontended=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);}}
/**
* Returns the current value. The returned value is <em>NOT</em>
* an atomic snapshot; invocation in the absence of concurrent
* updates returns an accurate result, but concurrent updates that
* occur while the value is being calculated might not be
* incorporated.
*
* @return the current value
*/publiclongget(){Cell[]as=cells;Cella;longresult=base;if(as!=null){for(inti=0;i<as.length;++i){if((a=as[i])!=null)result=function.applyAsLong(result,a.value);}}returnresult;}
/**
* Resets variables maintaining updates to the identity value.
* This method may be a useful alternative to creating a new
* updater, but is only effective if there are no concurrent
* updates. Because this method is intrinsically racy, it should
* only be used when it is known that no threads are concurrently
* updating.
*/publicvoidreset(){Cell[]as=cells;Cella;base=identity;if(as!=null){for(inti=0;i<as.length;++i){if((a=as[i])!=null)a.value=identity;}}}/**
* Equivalent in effect to {@link #get} followed by {@link
* #reset}. This method may apply for example during quiescent
* points between multithreaded computations. If there are
* updates concurrent with this method, the returned value is
* <em>not</em> guaranteed to be the final value occurring before
* the reset.
*
* @return the value before reset
*/publiclonggetThenReset(){Cell[]as=cells;Cella;longresult=base;base=identity;if(as!=null){for(inti=0;i<as.length;++i){if((a=as[i])!=null){longv=a.value;a.value=identity;result=function.applyAsLong(result,v);}}}returnresult;}