本节学习ArrayBlockingQueue的源码:
1.首先看类的定义
public class ArrayBlockingQueue<E> extends AbstractQueue<E>
implements BlockingQueue<E>, java.io.Serializable
可以看到类继承了AbstractQueue且实现了接口BlockingQueue
public abstract class AbstractQueue<E>
extends AbstractCollection<E>
implements Queue<E> {
/**
* 构造方法
*/
protected AbstractQueue() {
}
/**
* 添加元素,如果添加成功,则返回true,否则异常
*/
public boolean add(E e) {
if (offer(e))
return true;
else
throw new IllegalStateException("Queue full");
}
/**
* 移除元素,如果移除成功,返回被移除的元素,否则异常
*/
public E remove() {
E x = poll();
if (x != null)
return x;
else
throw new NoSuchElementException();
}
/**
* 获取元素,如果获取到元素,则返回,否则异常
*/
public E element() {
E x = peek();
if (x != null)
return x;
else
throw new NoSuchElementException();
}
/**
* 清空队列
*/
public void clear() {
while (poll() != null)
;
}
/**
* 添加元素,如果添加成功,则返回true,否则返回false,或者异常
*/
public boolean addAll(Collection<? extends E> c) {
if (c == null)
throw new NullPointerException();
if (c == this)
throw new IllegalArgumentException();
boolean modified = false;
for (E e : c)
if (add(e))
modified = true;
return modified;
}
}
2.类的变量信息
/** 使用数组保存队列元素 */
final Object[] items;
/** 下一个去除或者移除的元素的下标位置 */
int takeIndex;
/** 下一个添加的元素的下标位置 */
int putIndex;
/** 队列中元素的个数 */
int count;
/** 控制所有访问的重入锁 */
final ReentrantLock lock;
/** 取出元素的条件 */
private final Condition notEmpty;
/** 添加元素的条件 */
private final Condition notFull;
/**
* Shared state for currently active iterators, or null if there
* are known not to be any. Allows queue operations to update
* iterator state.
*/
transient Itrs itrs = null;
3.添加元素的四个方法:
3.1 add 调用的抽象队列中的添加方法,会抛异常
public boolean add(E e) {
return super.add(e);
}
3.2 offer如果队列满了,则直接返回false。
public boolean offer(E e) {
checkNotNull(e);//元素判空,如果为空,则抛空指针异常
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (count == items.length)//如果队列元素满了,则返回false
return false;
else {
enqueue(e);//否则
return true;
}
} finally {
lock.unlock();
}
}
private void enqueue(E x) {
// assert lock.getHoldCount() == 1;
// assert items[putIndex] == null;
final Object[] items = this.items;
items[putIndex] = x;//设置putIndex下标元素为x
if (++putIndex == items.length)//如果putIndex加1后的长度等于数组长度,则设置putIndex为0
putIndex = 0;
count++;//数组元素个数+1
notEmpty.signal();//唤醒取元素条件
}
3.3 put 可以中断且如果队列元素满了,要进入等待状态。
public void put(E e) throws InterruptedException {
checkNotNull(e);//非空校验
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();//可以中断的锁
try {
while (count == items.length)//如果队列元素满了
notFull.await();//添加元素的条件等待
enqueue(e);//否则添加元素
} finally {
lock.unlock();
}
}
3.4 offer可终端,超时时间内可以阻塞等待,超时后如果队列还是满的,则返回false。
public boolean offer(E e, long timeout, TimeUnit unit)
throws InterruptedException {
checkNotNull(e);//非空校验
long nanos = unit.toNanos(timeout);//超时时间
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == items.length) {
if (nanos <= 0)//如果队列满了且超过等待时间,则返回false
return false;
nanos = notFull.awaitNanos(nanos);//否则添加元素的条件等待nanos时间
}
enqueue(e);
return true;
} finally {
lock.unlock();
}
}
4.取元素的几个方法
4.1 poll 如果队列中没有元素,则返回null
public E poll() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return (count == 0) ? null : dequeue();
} finally {
lock.unlock();
}
}
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;//设置元素为null
if (++takeIndex == items.length)
takeIndex = 0;
count--;
if (itrs != null)
itrs.elementDequeued();
notFull.signal();//添加元素的条件唤醒
return x;
}
4.2 take 可中断,如果队列为空,则进入等待。
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0)//如果没有可移除的元素,则移除元素的条件等待
notEmpty.await();
return dequeue();//移除元素
} finally {
lock.unlock();
}
}
4.3 poll 可中断,如果队列为空,在等待时间内会进入等待状态,过了等待时间返回null。
public E poll(long timeout, TimeUnit unit) throws InterruptedException {
long nanos = unit.toNanos(timeout);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0) {
if (nanos <= 0)
return null;
nanos = notEmpty.awaitNanos(nanos);
}
return dequeue();
} finally {
lock.unlock();
}
}
4.4 remove
public boolean remove(Object o) {
if (o == null) return false;
final Object[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (count > 0) {//如果队列不为空
final int putIndex = this.putIndex;
int i = takeIndex;
do {
if (o.equals(items[i])) {
removeAt(i); 移除元素
return true;
}
if (++i == items.length)
i = 0;
} while (i != putIndex);
}
return false;
} finally {
lock.unlock();
}
}
void removeAt(final int removeIndex) {
// assert lock.getHoldCount() == 1;
// assert items[removeIndex] != null;
// assert removeIndex >= 0 && removeIndex < items.length;
final Object[] items = this.items;
if (removeIndex == takeIndex) {
// removing front item; just advance
items[takeIndex] = null;
if (++takeIndex == items.length)
takeIndex = 0;
count--;
if (itrs != null)
itrs.elementDequeued();
} else {
// an "interior" remove
// slide over all others up through putIndex.
final int putIndex = this.putIndex;
for (int i = removeIndex;;) {
int next = i + 1;
if (next == items.length)
next = 0;
if (next != putIndex) {
items[i] = items[next];
i = next;
} else {
items[i] = null;
this.putIndex = i;
break;
}
}
count--;
if (itrs != null)
itrs.removedAt(removeIndex);
}
notFull.signal();
}
5 其他方法
5.1 peek 返回下个要移除的元素值。
public E peek() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return itemAt(takeIndex); // null when queue is empty
} finally {
lock.unlock();
}
}
5.2 size 返回队列元素的个数
public int size() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return count;
} finally {
lock.unlock();
}
}
5.3 remainingCapacity 返回队列剩余的空间
public int remainingCapacity() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return items.length - count;
} finally {
lock.unlock();
}
}
5.4 contains判断队列中是否包含元素o
public boolean contains(Object o) {
if (o == null) return false;
final Object[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (count > 0) {
final int putIndex = this.putIndex;
int i = takeIndex;
do {
if (o.equals(items[i]))
return true;
if (++i == items.length)
i = 0;
} while (i != putIndex);
}
return false;
} finally {
lock.unlock();
}
}
5.5 clear 清空队列,且唤醒所有添加数据的条件
public void clear() {
final Object[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lock();
try {
int k = count;
if (k > 0) {
final int putIndex = this.putIndex;
int i = takeIndex;
do {
items[i] = null;
if (++i == items.length)
i = 0;
} while (i != putIndex);
takeIndex = putIndex;
count = 0;
if (itrs != null)
itrs.queueIsEmpty();
for (; k > 0 && lock.hasWaiters(notFull); k--)
notFull.signal();
}
} finally {
lock.unlock();
}
}
总结:
有界阻塞队列,底层数据结构是数组。
同步控制使用的重入锁和condition。