基本類型int的遞增等操作並不是線程安全的,加上synchronized又會影響性能,因此在併發情況下我們應該使用AtomicInteger,下面通過一個例子驗證一哈。
public class TestAtomicInteger {
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(new AtomicIntegerThread());
executorService.execute(new AtomicIntegerThread());
executorService.execute(new AtomicIntegerThread());
executorService.execute(new AtomicIntegerThread());
executorService.execute(new AtomicIntegerThread());
executorService.execute(new IntegerThread());
executorService.execute(new IntegerThread());
executorService.execute(new IntegerThread());
executorService.execute(new IntegerThread());
executorService.execute(new IntegerThread());
executorService.shutdown();
boolean b = executorService.awaitTermination(5, TimeUnit.SECONDS);
if(b) {
System.out.println("AtomicIntegerThread:" + AtomicIntegerThread.ai.get());
System.out.println("IntegerThread:" + IntegerThread.i);
}else{
System.out.println("time out.");
}
}
}
class AtomicIntegerThread implements Runnable {
static AtomicInteger ai = new AtomicInteger(0);
@Override
public void run() {
for (int m = 0; m < 10000000; m++) {
ai.getAndIncrement();
}
}
}
class IntegerThread implements Runnable {
static int i = 0;
@Override
public void run() {
for (int m = 0; m < 10000000; m++) {
i++;
}
}
}
運行結果如下:
AtomicIntegerThread:50000000
IntegerThread:26507929
AtomicInteger線程安全的運算是基於sun.misc.Unsafe類中的本地方法,關於Unsafe的介紹可以參考sun.misc.Unsafe。
AtomicInteger的常用方法:
//獲取當前值
int get();
//設置指定值
void set(int newValue)
//設置指定值並返回原來的值
int getAndSet(int newValue)
// i++
int getAndIncrement()
// ++i
int incrementAndGet()
// i--
int getAndDecrement()
// --i
int decrementAndGet()
//當前值加上delta,返回以前的值
int getAndAdd(int delta)
//當前值加上delta,返回新的值
int addAndGet(int delta)
//如果當前值等於入參expect,則把值設爲update,並返回ture,如果不等則返回false
boolean compareAndSet(int expect, int update)
// 1.8新增方法,更新當前值,返回以前的值
int getAndUpdate(IntUnaryOperator updateFunction)
// 1.8新增方法,更新當前值,返回更新後的值
int updateAndGet(IntUnaryOperator updateFunction)
// 1.8新增方法,更新當前值,返回以前的值
int getAndAccumulate(int x,IntBinaryOperator accumulatorFunction)
// 1.8新增方法,更新當前值,返回更新後的值
int accumulateAndGet(int x,IntBinaryOperator accumulatorFunction)
/**
* 演示AtomicInteger中1.8新增方法的使用方法
*/
@Test
public void operatorTest(){
AtomicInteger i = new AtomicInteger(0);
//lambda表達式中參數operand表示AtomicInteger的當前值
int andUpdate = i.getAndUpdate(operand -> ++operand);
System.out.println(andUpdate); //result: 0
System.out.println(i.get()); //result: 1
int i1 = i.updateAndGet(operand -> operand-2 );
System.out.println(i1); //result: -1
System.out.println(i.get()); //result: -1
//lambda表達式中參數left表示AtomicInteger的當前值、right表示前面那個參數5
int andAccumulate = i.getAndAccumulate(5, (left, right) -> left + right);
System.out.println(andAccumulate); //result: -1
System.out.println(i.get()); //result: 4
int i2 = i.accumulateAndGet(4, (left, right) -> left + right);
System.out.println(i2); //result: 8
System.out.println(i.get()); //result: 8
}