//掩码,用来计算槽位
final int mask;
//生产者下标
volatile long producerIndex;
//用于控制并发的producerIndex伴生成员变量
@SuppressWarnings("rawtypes")
static final AtomicLongFieldUpdater PRODUCER_INDEX =
AtomicLongFieldUpdater.newUpdater(SpsclinkedArrayQueue.class,
"producerIndex");
//当前生产数组
AtomicReferenceArray
构造方法
SpsclinkedArrayQueue(int linkSize) {
int c = Queues.ceilingNextPowerOfTwo(Math.max(8, linkSize));
this.producerArray = this.consumerArray = new AtomicReferenceArray<>(c + 1);
this.mask = c - 1;
}
public T poll() {
long ci = consumerIndex;
//将当前的消费数组赋值给a
AtomicReferenceArray a = consumerArray;
int m = mask;
//计算当前消费的下标
int offset = (int) ci & m;
//得到当前的下标
Object o = a.get(offset);
//如果元素为null,则表示没有元素可消费了,直接返回
if (o == null) {
return null;
}
//如果为NEXT则表示需要访问下一个数组了,更新a的值
if (o == NEXT) {
AtomicReferenceArray b = (AtomicReferenceArray) a.get(m + 1);
//将即将要废弃的消费数组的最后一个下标的设置为null,用于gc,避免下一个数组消费完后还有指针指向它,而无法正常被回收。
a.lazySet(m + 1, null);
//从新的消费数组获取元素
o = b.get(offset);
a = b;
consumerArray = b;
}
//将当前的消费下标设置为null
a.lazySet(offset, null);
CONSUMER_INDEX.lazySet(this, ci + 1);
return (T) o;
}