Java并发编程札记-(三)JUC原子类-03原子方式更新数组

时间:2022-05-01 18:01:34

今天学习AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray,这几个类的共同特点是都提供数组的原子方式访问和更新功能。下面以AtomicLongArray为代表,对这些类进行介绍。

AtomicLongArray可以用原子方式更新其元素的long数组,实例提供long类型数组的原子方式访问和更新功能。

API

//构造方法摘要
AtomicLongArray(int length)
//创建给定长度的新 AtomicLongArray。
AtomicLongArray(long[] array)
//创建与给定数组具有相同长度的新 AtomicLongArray,并从给定数组复制其所有元素。
//方法摘要
long addAndGet(int i, long delta)
//以原子方式将给定值添加到索引 i 的元素。
boolean compareAndSet(int i, long expect, long update)
//如果当前值 == 预期值,则以原子方式将该值设置为给定的更新值。
long decrementAndGet(int i)
//以原子方式将索引 i 的元素减1。
long get(int i)
//获取位置 i 的当前值。
long getAndAdd(int i, long delta)
//以原子方式将给定值与索引 i 的元素相加。
long getAndDecrement(int i)
//以原子方式将索引 i 的元素减 1。
long getAndIncrement(int i)
//以原子方式将索引 i 的元素加 1。
long getAndSet(int i, long newValue)
//以原子方式将位置 i 的元素设置为给定值,并返回旧值。
long incrementAndGet(int i)
//以原子方式将索引 i 的元素加1。
void lazySet(int i, long newValue)
//最终将位置 i 的元素设置为给定值。
int length()
//返回该数组的长度。
void set(int i, long newValue)
//将位置 i 的元素设置为给定值。
String toString()
//返回数组当前值的字符串表示形式。
boolean weakCompareAndSet(int i, long expect, long update)
//如果当前值 == 预期值,则以原子方式将该值设置为给定的更新值。
//以下是JDK1.8新增的部分
long getAndUpdate(int i, LongUnaryOperator updateFunction)
//将当前值以原子方式更新为updateFunction方法的结果,并返回更新前的值
long updateAndGet(int i, LongUnaryOperator updateFunction)
//将当前值以原子方式更新为updateFunction方法的结果,并返回更新后的值
long getAndAccumulate(int i, long x, LongBinaryOperator accumulatorFunction)
//将当前值以原子方式更新为updateFunction方法的结果(方法参数为x和当前值),并返回更新前的值
long accumulateAndGet(int i, long x, LongBinaryOperator accumulatorFunction)
//将当前值以原子方式更新为updateFunction方法的结果(方法参数为x和当前值),并返回更新后的值

例1:long型数组的原子访问和更新

import java.util.Arrays;

public class AtomicLongArrayDemo {

public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
Thread thread = new Thread() {
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(("[100, 100, 100, 100, 100]").equals(Arrays.toString(Counter.addOne())))
System.out.println("计数器值最终值为[100, 100, 100, 100, 100]");
}
};
thread.start();
}
}
}
class Counter {
private static long[] counter = new long[]{0, 0, 0, 0, 0};

public static long[] addOne() {
for(int i=0;i<counter.length;i++)
++counter[i];
return counter;
}
}

测试程序在连续运行100次将数组所有元素加一的操作后,判断计数器值是否为100, 100, 100, 100, 100],如果为100, 100, 100, 100, 100]就打印计数器值最终值为100, 100, 100, 100, 100],否则就什么都不打印。
数次运行程序后,发现大多数结果是什么都没有打印,说明此计数器在多线程环境下不可用。

import java.util.concurrent.atomic.AtomicLongArray;

public class AtomicLongArrayDemo {

public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
Thread thread = new Thread() {
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (("[100, 100, 100, 100, 100]").equals(Counter.addOne().toString())) {
System.out.println("计数器值最终值为[100, 100, 100, 100, 100]");
}
}
};
thread.start();
}
}
}

class Counter {
private static AtomicLongArray counter = new AtomicLongArray(new long[] {0, 0, 0, 0, 0});

public static AtomicLongArray addOne() {
for(int i=0;i<counter.length();i++)
counter.incrementAndGet(i);
return counter;
}
}

数次运行程序后,发现结果全部为计数器值最终值为[100, 100, 100, 100, 100]

实现原理

与AtomicLong相同,AtomicLong也是基于CAS实现的。

AtomicIntegerArray、AtomicReferenceArray与AtomicLongArray很相似,就不多做介绍了。

本文就讲到这里,想了解Java并发编程更多内容请参考:

END.