2016-03-15 235 views
9

是否有任何AtomicInteger.accumulateAndGet()无法替换为AtomicInteger.updateAndGet()的情况,还是只是方便参考?AtomicInteger.updateAndGet()和AtomicInteger.accumulateAndGet()之间是否有任何功能差异?

这里有一个简单的例子,我看不出有任何功能上的差异:

AtomicInteger i = new AtomicInteger(); 
i.accumulateAndGet(5, Math::max); 
i.updateAndGet(x -> Math.max(x, 5)); 

显然,这同样适用于getAndUpdate()getAndAccumulate()

+2

是不是能够(重新)使用现有功能(或非捕获方法引用)的有用功能? 'i.incrementAndGet()'和'i.accumulateAndGet(1,Integer :: sum)'之间也没有功能上的区别...... – Holger

+0

@Holger accumulateAndGet()'后来加了,再加上它不能使用'Unsafe'。 'addAndGet(1)'可能是一个更好的例子,但即使在创建时不使用“不安全”。不过,我确实接受你的一般观点;这个问题只是为了澄清这是否确实是动机。 – shmosel

回答

4

如果有疑问,你可以看看implementation

public final int accumulateAndGet(int x, 
            IntBinaryOperator accumulatorFunction) { 
    int prev, next; 
    do { 
     prev = get(); 
     next = accumulatorFunction.applyAsInt(prev, x); 
    } while (!compareAndSet(prev, next)); 
    return next; 
} 

public final int updateAndGet(IntUnaryOperator updateFunction) { 
    int prev, next; 
    do { 
     prev = get(); 
     next = updateFunction.applyAsInt(prev); 
    } while (!compareAndSet(prev, next)); 
    return next; 
} 

他们一行只不同,显然accumulateAndGet可以通过updateAndGet简单地表示:

public final int accumulateAndGet(int x, 
            IntBinaryOperator accumulatorFunction) { 
    return updateAndGet(prev -> accumulatorFunction.applyAsInt(prev, x)); 
} 

所以updateAndGet是较为基本操作和accumulateAndGet是一个有用的捷径。如果你的x是不能有效地最终这种快捷方式可能会非常有用:

int nextValue = 5; 
if(something) nextValue = 6; 
i.accumulateAndGet(nextValue, Math::max); 
// i.updateAndGet(prev -> Math.max(prev, nextValue)); -- will not work 
1

在有些情况下可以使用accumulateAndGet回避的实例创建情况。

这不是一个真正的功能差异,但它可能是有用的知道。

请看下面的例子:

void increment(int incValue, AtomicInteger i) { 
    // The lambda is closed over incValue. Because of this the created IntUnaryOperator 
    // will have a field which contains incValue. Because of this a new instance must 
    // be allocated on every call to the increment method. 
    i.updateAndGet(value -> incValue + value); 

    // The lambda is not closed over anything. The same IntBinaryOperator instance 
    // can be used on every call to the increment method, nothing need to be allocated. 
    i.accumulateAndGet(incValue, (incValueParam, value) -> incValueParam + value); 
} 

实例的作品一般都不贵,但也很重要的,是非常常用的性能敏感地点短操作摆脱。

有关何时重用lambda实例的更多信息,请参阅this answer

相关问题