java atomic
原子變量提供各種原子操作陶耍,多線程場(chǎng)景下操作不需要加鎖畜晰,性能非常好
簡例
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
: 返回當(dāng)前 int 值 -
incrementAndGet
: 自增筐骇,返回自增后的值 -
getAndIncrement
: 自增敌蜂,發(fā)揮自增前的值 -
addAndGet
: 加上一個(gè) int拾枣,并且獲取加上之后的值 -
getAndAdd
: 加上一個(gè) int庆械,并且返回加上之前的值 -
compareAndSet
: 當(dāng)前值與參數(shù)相等時(shí)薇溃,才設(shè)置當(dāng)前值,返回是否設(shè)置成功 -
compareAndExchange
: 當(dāng)前值與參數(shù)相等時(shí)缭乘,才設(shè)置當(dāng)前值沐序,返回老的值
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
的接口類似,只是每個(gè)接口都增加一個(gè) index
參數(shù)
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
: 獲取當(dāng)前引用對(duì)象 -
getAndSet
: 設(shè)置新的引用忿峻,并返回老的引用 -
compareAndSet
: 當(dāng)前值與參數(shù)相等時(shí)薄啥,才設(shè)置當(dāng)前值,返回是否設(shè)置成功 -
compareAndExchange
: 當(dāng)前值與參數(shù)相等時(shí)逛尚,才設(shè)置當(dāng)前值垄惧,返回老的值 -
accumulateAndGet
: 用當(dāng)前值和參數(shù)一起執(zhí)行 BinaryOpterator 的結(jié)果設(shè)置成當(dāng)前值,返回新的值 -
getAndAccumulate
: 用當(dāng)前值和參數(shù)一起執(zhí)行 BinaryOpterator 的結(jié)果設(shè)置成當(dāng)前值绰寞,返回老的值
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 的基礎(chǔ)上增加一個(gè) stamp 概念到逊,stamp 可理解為一個(gè)版本號(hào),即使兩個(gè)相等值相等滤钱,還可以通過版本號(hào)來區(qū)分
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
累加器觉壶,內(nèi)部采用多個(gè) atomic
變量實(shí)現(xiàn),減少由于多線程競爭帶來的性能開銷件缸,LongAccumulator
通過一個(gè) BinaryOperator
和一個(gè)初始值構(gòu)造而成铜靶,而 LongAddr
相當(dāng)于 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);
}