AtomicInteger.updateAndGet()和AtomicInteger.accumulateAndGet()之间是否存在任何功能差异?

时间:2016-03-15 21:40:17

标签: java lambda java-8 atomic atomicinteger

是否有任何情况AtomicInteger.accumulateAndGet()无法替换为AtomicInteger.updateAndGet(),或者只是方便参考的方便?

这是一个简单的例子,我没有看到任何功能差异:

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

显然,getAndUpdate()getAndAccumulate()也是如此。

2 个答案:

答案 0 :(得分:8)

如有疑问,您可以查看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 :(得分:4)

有些情况下,可以使用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.
    //
    // It can be cached in a field, or maybe the optimizer is able 
    // to reuse it automatically.
    IntBinaryOperator accumulatorFunction =
            (incValueParam, value) -> incValueParam + value;

    i.accumulateAndGet(incValue, accumulatorFunction);
}

实例创建通常并不昂贵,但对于在性能敏感位置经常使用的短操作来说非常重要。

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

相关问题