對int數組中元素的操做不是原子性的,因此存在併發操做時,咱們應該使用AtomicIntegerArray類來代替int數組。
下面是驗證演示代碼:java
public class AtomicIntegerArrayDemo { static AtomicIntegerArray aiArr = new AtomicIntegerArray(5); static int[] intArr = new int[5]; /** * 併發測試,對數組的每一個元素進行遞增操做 */ public static void main(String[] args) throws InterruptedException { ExecutorService threadPool = Executors.newCachedThreadPool(); for(int t = 0; t < 5; t++) { threadPool.execute(() -> { for (int i = 0; i < 1000000; i++) { aiArr.getAndIncrement(i % 5); } }); threadPool.execute(() -> { for (int i = 0; i < 1000000; i++) { intArr[i % 5]++; } }); } threadPool.shutdown(); boolean b = threadPool.awaitTermination(5, TimeUnit.SECONDS); if(b) { System.out.println("aiArr:" + aiArr.toString()); System.out.println("intArr:" + Arrays.toString(intArr)); }else{ System.out.println("time out."); } } }
運行結果:數組
D:\Java\jdk1.8.0_171\bin\java.exe "-javaagent:D:\JetBrains\IntelliJ IDEA aiArr:[1000000, 1000000, 1000000, 1000000, 1000000] intArr:[892703, 891096, 892369, 892372, 893754]
//獲取數組長度 int length() //獲取數組中下標爲i的元素的值 int get(int i) //設置數組中下標爲i的元素的值爲newValue void set(int i, int newValue) //設置數組中下標爲i的元素的值爲newValue,返回之前的值 int getAndSet(int i, int newValue) //若是數組中下標爲i的元素的值等於入參expect,則把值修改成update,並返回ture,若是不等則不修改並返回false boolean compareAndSet(int i, int expect, int update) // arr[i]++ int getAndIncrement(int i) // arr[i]-- int getAndDecrement(int i) // ++arr[i] int incrementAndGet(int i) // --arr[i] int decrementAndGet(int i) //數組中下標爲i的元素的值加上delta,返回之前的值 int getAndAdd(int i, int delta) //數組中下標爲i的元素的值加上delta,返回新的值 int addAndGet(int i, int delta) //1.8新增方法,更新當前值,返回之前的值 int getAndUpdate(int i, IntUnaryOperator updateFunction) // 1.8新增方法,更新當前值,返回更新後的值 int updateAndGet(int i, IntUnaryOperator updateFunction) // 1.8新增方法,更新當前值,返回之前的值 int getAndAccumulate(int i, int x, IntBinaryOperator accumulatorFunction) // 1.8新增方法,更新當前值,返回更新後的值 int accumulateAndGet(int i, int x, IntBinaryOperator accumulatorFunction)
** * 1.8新增方法演示 */ @Test public void atomicIntegerArrayMethodTest(){ AtomicIntegerArray arr = new AtomicIntegerArray(2); arr.set(0, 10); //lambda表達式中參數operand表示數組下標爲0的元素當前值 int i1 = arr.getAndUpdate(0, operand -> operand / 2); System.out.println(i1); // result: 10 System.out.println(arr.get(0)); // result: 5 int i2 = arr.updateAndGet(0, operand -> operand * 3); System.out.println(i2); // result: 15 System.out.println(arr.get(0)); // result: 15 //lambda表達式中參數left表示數組下標爲0的元素當前值,right表示第二個參數2 int i3 = arr.getAndAccumulate(0, 2, (left, right) -> left * right); System.out.println(i3); // result: 15 System.out.println(arr.get(0)); // result: 30 int i4 = arr.accumulateAndGet(0, 2, (left, right) -> left * right); System.out.println(i4); // result: 60 System.out.println(arr.get(0)); // result: 60 }
AtomicIntegerFieldUpdater是用來原子的操做對象中int類型字段的。 下面是驗證演示代碼:併發
public class AtomicIntegerFieldUpdaterDemo { /** * 併發測試,對Counter的index字段進行遞增操做 */ public static void main(String[] args) throws InterruptedException { Counter counter1 = new Counter(); AtomicIntegerFieldUpdater<Counter> counterIndexFieldUpdater = AtomicIntegerFieldUpdater.newUpdater(Counter.class, "index"); Counter counter2 = new Counter(); ExecutorService threadPool = Executors.newCachedThreadPool(); for(int t = 0; t < 5; t++) { threadPool.execute(() -> { for (int i = 0; i < 1000000; i++) { counter1.index++; } }); threadPool.execute(() -> { for (int i = 0; i < 1000000; i++) { counterIndexFieldUpdater.getAndIncrement(counter2); } }); } threadPool.shutdown(); boolean b = threadPool.awaitTermination(5, TimeUnit.SECONDS); if(b) { System.out.println("counter1.index:" + counter1.index); System.out.println("counter2.index:" + counterIndexFieldUpdater.getAndIncrement(counter2)); }else{ System.out.println("time out."); } } } class Counter{ /** 必須是volatile修飾的 */ public volatile int index = 0; }
運行結果:學習
D:\Java\jdk1.8.0_171\bin\java.exe "-javaagent:D:\JetBrains\IntelliJ IDEA counter1.index:4192522 counter2.index:5000000
值得注意的是,使用的時候注意以下幾點:測試
//建立AtomicIntegerFieldUpdater對象,tclass爲須要操做對象的類型,fieldName爲須要操做字段名稱 static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) //若是obj中指定字段的值等於expect,則把該字段的值設爲update boolean compareAndSet(T obj, int expect, int update) //把obj中指定字段的值設置爲newValue void set(T obj, int newValue); //返回obj中指定字段的值 int get(T obj); //把obj中指定字段的值設置爲newValue,返回之前的值 int getAndSet(T obj, int newValue) //i++ int getAndIncrement(T obj) //++i int incrementAndGet(T obj) //i-- int getAndDecrement(T obj) //--i decrementAndGet(T obj) //把obj中指定字段的值加上delta,返回之前的值 int getAndAdd(T obj, int delta) //把obj中指定字段的值加上delta,返回更新後的值 int addAndGet(T obj, int delta) //1.8新增方法,更obj中指定字段的值,返回之前的值 int getAndUpdate(T obj, IntUnaryOperator updateFunction) //1.8新增方法,更obj中指定字段的值,返回更新後的值 int updateAndGet(T obj, IntUnaryOperator updateFunction) //1.8新增方法,更obj中指定字段的值,返回之前的值 int getAndAccumulate(T obj, int x, IntBinaryOperator accumulatorFunction) //1.8新增方法,更obj中指定字段的值,返回更新後的值 int accumulateAndGet(T obj, int x, IntBinaryOperator accumulatorFunction)