java atomic

java atomic

原子變量提供各類原子操做,多線程場景下操做不須要加鎖,性能很是好java

簡例

AtomicInteger ai = new AtomicInteger(10);
ExecutorService es = Executors.newCachedThreadPool();

long endTime = System.currentTimeMillis() + 100;
for (int i = 0; i < 10; i++) {
    es.execute(() -> {
        while (System.currentTimeMillis() < endTime) {
            System.out.println(ai.incrementAndGet());
            System.out.println(ai.addAndGet(1));
        }
    });
}

try {
    es.shutdown();
    while (!es.awaitTermination(1, TimeUnit.SECONDS)) {
        // nothing to do
    }
} catch (InterruptedException e) {
    e.printStackTrace();
}

AtomicInteger

  • get: 返回當前 int 值
  • incrementAndGet: 自增,返回自增後的值
  • getAndIncrement: 自增,發揮自增前的值
  • addAndGet: 加上一個 int,而且獲取加上以後的值
  • getAndAdd: 加上一個 int,而且返回加上以前的值
  • compareAndSet: 當前值與參數相等時,才設置當前值,返回是否設置成功
  • compareAndExchange: 當前值與參數相等時,才設置當前值,返回老的值
AtomicInteger i = new AtomicInteger(10);
assertEquals(i.get(), 10);
assertEquals(i.incrementAndGet(), 11);
assertEquals(i.getAndIncrement(), 11);
assertEquals(i.get(), 12);
assertEquals(i.addAndGet(10), 22);
assertEquals(i.getAndAdd(10), 22);
assertEquals(i.get(), 32);
assertTrue(i.compareAndSet(32, 10));
assertFalse(i.compareAndSet(32, 10));
assertEquals(i.compareAndExchange(10, 22), 10);
assertEquals(i.compareAndExchange(10, 22), 22);

AtomicIntegerArray

AtomicInteger 的接口相似,只是每一個接口都增長一個 index 參數git

AtomicIntegerArray ia = new AtomicIntegerArray(10);

for (int i = 0; i < 10; i++) {
    ia.set(i, i);
}

assertEquals(ia.get(5), 5);
assertEquals(ia.incrementAndGet(5), 6);
assertEquals(ia.incrementAndGet(5), 7);
assertEquals(ia.addAndGet(5, 10), 17);
assertTrue(ia.compareAndSet(5, 17, 15));
assertEquals(ia.compareAndExchange(5, 15, 10), 15); // 返回老值

AtomicReference

  • get: 獲取當前引用對象
  • getAndSet: 設置新的引用,並返回老的引用
  • compareAndSet: 當前值與參數相等時,才設置當前值,返回是否設置成功
  • compareAndExchange: 當前值與參數相等時,才設置當前值,返回老的值
  • accumulateAndGet: 用當前值和參數一塊兒執行 BinaryOpterator 的結果設置成當前值,返回新的值
  • getAndAccumulate: 用當前值和參數一塊兒執行 BinaryOpterator 的結果設置成當前值,返回老的值
AtomicReference<Integer> i = new AtomicReference<>();
assertEquals(i.get(), null);
assertEquals(i.getAndSet(10), null);
assertEquals(i.get(), Integer.valueOf(10));
assertEquals(i.compareAndExchange(10, 11), Integer.valueOf(10));
assertTrue(i.compareAndSet(11, 12));
assertEquals(i.accumulateAndGet(3, (x, y) -> x + y), Integer.valueOf(15));
assertEquals(i.getAndAccumulate(3, (x, y) -> x + y), Integer.valueOf(15));

AtomicStampedReference

在 atomic 的基礎上增長一個 stamp 概念,stamp 可理解爲一個版本號,即便兩個相等值相等,還能夠經過版本號來區分github

AtomicStampedReference<Integer> i = new AtomicStampedReference<>(null, 0);
assertEquals(i.getReference(), null);
assertEquals(i.getStamp(), 0);
assertTrue(i.compareAndSet(null, 10, 0, 1));
assertEquals(i.getReference(), Integer.valueOf(10));
assertEquals(i.getStamp(), 1);

LongAccumulator

LongAccumulator 累加器,內部採用多個 atomic 變量實現,減小因爲多線程競爭帶來的性能開銷,LongAccumulator 經過一個 BinaryOperator 和一個初始值構造而成,而 LongAddr 至關於 new LongAccumulator((x, y) -> x + y, 0)多線程

{
    LongAccumulator i = new LongAccumulator((x, y) -> x + y, 0);
    i.accumulate(10);
    i.accumulate(20);
    assertEquals(i.get(), 30);
}
{
    LongAdder j = new LongAdder();
    j.add(10);
    j.add(20);
    assertEquals(j.sum(), 30);
}

連接

相關文章
相關標籤/搜索