对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)