VarHandle
班级。正如您在
Atomic
xxx
Array
AtomicIntegerArray
,这些类也使用
瓦汉德尔
//[...]
private static final VarHandle AA
= MethodHandles.arrayElementVarHandle(int[].class);
private final int[] array;
//[...]
/**
* Returns the current value of the element at index {@code i},
* with memory effects as specified by {@link VarHandle#getVolatile}.
*
* @param i the index
* @return the current value
*/
public final int get(int i) {
return (int)AA.getVolatile(array, i);
}
/**
* Sets the element at index {@code i} to {@code newValue},
* with memory effects as specified by {@link VarHandle#setVolatile}.
*
* @param i the index
* @param newValue the new value
*/
public final void set(int i, int newValue) {
AA.setVolatile(array, i, newValue);
}
//[...]
首先创建一个
瓦汉德尔
这样地:
MethodHandles.arrayElementVarHandle(yourArrayClass)
例如,您可以输入
byte[].class
AtomicByteArray
你自己
然后您可以使用
set
xxx
(array, index, value)
和
get
xxx
(array, index)
array
是一种
yourArrayClass
,
index
是一种
int
,
value
是数组中元素的类型(
yourArrayClass.getComponentType()
请注意,例如,
yourArrayClass == byte[].class
但是你进去了
42
价值
,您将得到一个错误,因为
是一个
而不是
byte
Object...
参数:
java.lang.invoke.WrongMethodTypeException: cannot convert MethodHandle(VarHandle,byte[],int,byte)void to (VarHandle,byte[],int,int)void
请注意,在JDK 8及以下版本中
sun.misc.Unsafe
AtomicIntegerArray
:
//[...]
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);
}
private long checkedByteOffset(int i) {
if (i < 0 || i >= array.length)
throw new IndexOutOfBoundsException("index " + i);
return byteOffset(i);
}
private static long byteOffset(int i) {
return ((long) i << shift) + base;
}
//[...]
/**
* Gets the current value at position {@code i}.
*
* @param i the index
* @return the current value
*/
public final int get(int i) {
return getRaw(checkedByteOffset(i));
}
private int getRaw(long offset) {
return unsafe.getIntVolatile(array, offset);
}
/**
* 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
仍然是一个选项(尽管我认为获取实例有点棘手),但不鼓励这样做,因为您必须自己检查数组边界,如果您出错,它可能会导致Java进程出错,而
瓦汉德尔
不安全的
不受官方支持,可能随时被删除。
不安全的
仍在使用中
AtomicInteger
因为
.
Using JDK 9 Memory Order Modes
(我不得不说,我根本不是这方面的专家(到目前为止?)。
请注意,从今天起,您不能使用
在Kotlin,因为它包裹了vararg
对象
Object[]
看见
bug KT-26165
java.lang.invoke.WrongMethodTypeException: cannot convert MethodHandle(VarHandle,byte[],int,byte)void to (VarHandle,Object[])void
(现在应该修复)