[超级链接:Java并发学习系列-绪论]
[系列概述: Java并发22:Atomic系列-原子类型整体概述与类别划分]
本章主要对原子类型数组进行学习。
在java.util.concurrent.atomic中,原子类型数组有以下三种:
int[]
数组元素的原子性更新操作。long[]
数组元素的原子性更新操作。引用类型[]
数组元素的原子性更新操作。查看部分原子类型数组的源码:
/**
* An {@code int} array in which elements may be updated atomically.
* See the {@link java.util.concurrent.atomic} package
* specification for description of the properties of atomic
* variables.
* @since 1.5
* @author Doug Lea
*/
public class AtomicIntegerArray implements java.io.Serializable {
private static final long serialVersionUID = 2862133569453604235L;
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final int base = unsafe.arrayBaseOffset(int[].class);
private static final int shift;
private final int[] array;
static {
int scale = unsafe.arrayIndexScale(int[].class);
if ((scale & (scale - 1)) != 0)
throw new Error("data type scale not a power of two");
shift = 31 - Integer.numberOfLeadingZeros(scale);
}
//...
/**
* Sets the element at position {@code i} to the given value.
*
* @param i the index
* @param newValue the new value
*/
public final void set(int i, int newValue) {
unsafe.putIntVolatile(array, checkedByteOffset(i), newValue);
}
}
从上面的源码可知,原子类型在内部通过Unsafe类的native方法保证操作的原子性。
首先学习上述三种原子类型数组的通用方法,这些方法如下:
原子类型数组的通用方法与普通原子类型的通用方法类似,唯一的区别在于多了一个参数:index(数组元素下标)
实例代码:
//构造器
LOGGER.info("===========原子数组构造器");
//数组构造器
AtomicIntegerArray aIntArray = new AtomicIntegerArray(new int[]{1,2,3,4,5});
AtomicReferenceArray aStrArray = new AtomicReferenceArray<>(new String []{"David","Jone","Gray"});
LOGGER.info("AtomicIntegerArray(int[]):" + aIntArray.toString());
LOGGER.info("AtomicReferenceArray(String[]):" + aStrArray.toString());
//长度构造器
LOGGER.info("AtomicIntegerArray(length):" + new AtomicIntegerArray(10).toString());
LOGGER.info("AtomicIntegerReference(length):" + new AtomicReferenceArray(10).toString() + "\n");
//通用方法
LOGGER.info("===========原子数组通用方法:get/set/lazySet/getAndSet/CompareAndSet");
//get(index)
LOGGER.info("get(index):获取第i个元素----" + aStrArray.get(2).toString());
//set(index,newValue)
aStrArray.set(0,"Dock");
LOGGER.info("set(index,newValue):设置第i个元素的值----" + aStrArray.get(0).toString());
//lazySet(index,newValue)
aStrArray.lazySet(0,"Green");
LOGGER.info("lazySet(index,newValue):设置第i个元素的值(无可见性)----" + aStrArray.get(0).toString());
//getAndSet(index,newValue)
LOGGER.info("getAndSet(index,newValue):设置第i个元素的值,并返回此元素的旧值----" + aStrArray.getAndSet(0,"Merlin"));
//compareAndSet(index,expect,newValue)
LOGGER.info("compareAndSet(index,expect,newValue):如果第i个元素的值是期望的值,则设置新值,并返回执行结果----" + aStrArray.compareAndSet(0,"Merlin","Love"));
//length
LOGGER.info("length():数组长度----" + aStrArray.length());
LOGGER.info("weakCompareAndSet(index,expect,newValue)的实现的效果与compareAndSet(index,expect,newValue)一致,但可能失败[其实不会失败,因为其源代码与后者一致。]\n");
运行结果:
2018-03-25 15:42:55 INFO AtomicArrayDemo:21 - ===========原子数组构造器
2018-03-25 15:42:56 INFO AtomicArrayDemo:25 - AtomicIntegerArray(int[]):[1, 2, 3, 4, 5]
2018-03-25 15:42:56 INFO AtomicArrayDemo:26 - AtomicReferenceArray(String[]):[David, Jone, Gray]
2018-03-25 15:42:56 INFO AtomicArrayDemo:28 - AtomicIntegerArray(length):[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2018-03-25 15:42:56 INFO AtomicArrayDemo:29 - AtomicIntegerReference(length):[null, null, null, null, null, null, null, null, null, null]
2018-03-25 15:42:56 INFO AtomicArrayDemo:32 - ===========原子数组通用方法:get/set/lazySet/getAndSet/CompareAndSet
2018-03-25 15:42:56 INFO AtomicArrayDemo:34 - get(index):获取第i个元素----Gray
2018-03-25 15:42:56 INFO AtomicArrayDemo:37 - set(index,newValue):设置第i个元素的值----Dock
2018-03-25 15:42:56 INFO AtomicArrayDemo:40 - lazySet(index,newValue):设置第i个元素的值(无可见性)----Green
2018-03-25 15:42:56 INFO AtomicArrayDemo:42 - getAndSet(index,newValue):设置第i个元素的值,并返回此元素的旧值----Green
2018-03-25 15:42:56 INFO AtomicArrayDemo:44 - compareAndSet(index,expect,newValue):如果第i个元素的值是期望的值,则设置新值,并返回执行结果----true
2018-03-25 15:42:56 INFO AtomicArrayDemo:46 - length():数组长度----3
2018-03-25 15:42:56 INFO AtomicArrayDemo:47 - weakCompareAndSet(index,expect,newValue)的实现的效果与compareAndSet(index,expect,newValue)一致,但可能失败[其实不会失败,因为其源代码与后者一致。]
然后学习AtomicIntegerArray和AtomicLongArray独有的一些方法,这些方法如下:
i ++
,具有原子性和可见性。++ i
,具有原子性和可见性。i --
,具有原子性和可见性。-- i
,具有原子性和可见性。AtomicIntegerArray和AtomicLongArray的独有方法与AtomicInteger和AtomicLong的独有方法类似,唯一的区别在于多了一个参数:index(数组元素下标)
实例代码:
//AtomicIntegerArray和AtomicLongArray的独有方法:getAndAdd/addAndGet/i++/i--/++i/--i
LOGGER.info("===========AtomicIntegerArray和AtomicLongArray的独有方法:getAndAdd/addAndGet/i++/i--/++i/--i");
//getAndAdd(index,newValue)和addAndGet(index,newValue)
aIntArray.set(2,0);
LOGGER.info("i = 2,value = " + aIntArray.get(2));
LOGGER.info("getAndAdd(index,newValue):增量计算,返回旧值----" + aIntArray.getAndAdd(2,2));
aIntArray.set(2,0);
LOGGER.info("addAndGet(index,newValue):增量计算,返回新值----" + aIntArray.addAndGet(2,2));
//getAndIncrement(index)和incrementAndGet(index)
aIntArray.set(2,0);
LOGGER.info("i = 2,value = " + aIntArray.get(2));
LOGGER.info("getAndIncrement(index):自增计算,返回旧值----" + aIntArray.getAndIncrement(2));
aIntArray.set(2,0);
LOGGER.info("incrementAndGet(index):自增计算,返回新值----" + aIntArray.incrementAndGet(2));
//getAndDecrement(index)decrementAndGet(index)
aIntArray.set(2,0);
LOGGER.info("i = 2,value = " + aIntArray.get(2));
LOGGER.info("getAndDecrement(index):自减计算,返回旧值----" + aIntArray.getAndDecrement(2));
aIntArray.set(2,0);
LOGGER.info("decrementAndGet(index):自减计算,返回新值----" + aIntArray.decrementAndGet(2));
运行结果:
2018-03-25 15:42:56 INFO AtomicArrayDemo:50 - ===========AtomicIntegerArray和AtomicLongArray的独有方法:getAndAdd/addAndGet/i++/i--/++i/--i
2018-03-25 15:42:56 INFO AtomicArrayDemo:53 - i = 2,value = 0
2018-03-25 15:42:56 INFO AtomicArrayDemo:54 - getAndAdd(index,newValue):增量计算,返回旧值----0
2018-03-25 15:42:56 INFO AtomicArrayDemo:56 - addAndGet(index,newValue):增量计算,返回新值----2
2018-03-25 15:42:56 INFO AtomicArrayDemo:59 - i = 2,value = 0
2018-03-25 15:42:56 INFO AtomicArrayDemo:60 - getAndIncrement(index):自增计算,返回旧值----0
2018-03-25 15:42:56 INFO AtomicArrayDemo:62 - incrementAndGet(index):自增计算,返回新值----1
2018-03-25 15:42:56 INFO AtomicArrayDemo:65 - i = 2,value = 0
2018-03-25 15:42:56 INFO AtomicArrayDemo:66 - getAndDecrement(index):自减计算,返回旧值----0
2018-03-25 15:42:56 INFO AtomicArrayDemo:68 - decrementAndGet(index):自减计算,返回新值-----1