ArrayBlockingQueue
比较简单,基于数组实现的有界阻塞队列。BlockingQueue接口中有介绍,所有该接口实现都是线程安全的。 所有排队方法都使用内部锁或其他形式的并发控制以原子方式实现其效果。
public ArrayBlockingQueue(int capacity) {
this(capacity, false);
}
public ArrayBlockingQueue(int capacity, boolean fair) {
if (capacity <= 0)
throw new IllegalArgumentException();
this.items = new Object[capacity];
lock = new ReentrantLock(fair);
notEmpty = lock.newCondition();
notFull = lock.newCondition();
}
很显然,ArrayBlockingQueue的线程安全是基于lock与condition实现的,且支持可选的公平与非公平策略,这部分知识就不在这里介绍了。
/** The queued items */
final Object[] items;
/** items index for next take, poll, peek or remove */
int takeIndex;
/** items index for next put, offer, or add */
int putIndex;
/** Number of elements in the queue */
int count;
/** Main lock guarding all access */
final ReentrantLock lock;
/** Condition for waiting takes */
private final Condition notEmpty;
/** Condition for waiting puts */
private final Condition notFull;
这里关注一下putIndex,takeIndex,分别对应入队和出队。
putIndex,下一个入队元素的下标,队列null或已满时置为0
takeIndex,下一次移除操作对应的元素的下标
private void enqueue(E x) {
// assert lock.getHoldCount() == 1;
// assert items[putIndex] == null;
final Object[] items = this.items;
items[putIndex] = x;
if (++putIndex == items.length)
putIndex = 0;
count++;
notEmpty.signal();
}
private E dequeue() {
// assert lock.getHoldCount() == 1;
// assert items[takeIndex] != null;
final Object[] items = this.items;
@SuppressWarnings("unchecked")
E x = (E) items[takeIndex];
items[takeIndex] = null;
if (++takeIndex == items.length)
takeIndex = 0;
count--;
if (itrs != null)
itrs.elementDequeued();
notFull.signal();
return x;
}
ArrayBlockingQueue支持在迭代的过程中不通过迭代器对队列的结构做出修改(但也仅限于当前线程,迭代过程中是全称加锁的),不会抛出ConcurrentModificationException,但是迭代结果不会受影响,保持迭代开始时的数据。
关于该队列的迭代器,实现比较麻烦,不是很想去关心,暂且放下。
这个类确实比较简单,就不多写了。