sp; try {
//如果队列已满
while (count == items.length) {
//超时则返回入队失败,否则生产者等待对应时间
if (nanos <= 0)
return false;
nanos = notFull.awaitNanos(nanos);
}
//入队
enqueue(e);
return true;
} finally {
//解锁
lock.unlock();
}
}
直接使用可重入锁保证同步,如果队列已满,在此期间判断是否超时,超时就返回,未超时等待;未满则执行入队方法
private void enqueue(E x) {
//队列数组
final Object[] items = this.items;
//往入队下标添加值
items[putIndex] = x;
//自增入队下标 如果已满则定位到0 成环
if (++putIndex == items.length)
putIndex = 0;
//统计数量增加
count++;
//唤醒消费者
notEmpty.signal();
}
在入队中,主要是添加元素、修改下次添加的下标、统计队列中的元素和唤醒消费者,到这以及可以说明它的实现是环形数组
ArrayBlockingQueue
由环形数组实现的阻塞队列,固定容量不支持动态扩容,使用非公平的ReertrantLock
保证入队、出队操作的原子性,使用两个等待队列存储等待的生产者、消费者,适用于在并发量不大的场景
LinkedBlockingQueue
LinkedBlockingQueue
从名称上来看,就是使用链表实现的,我们来看看它的关键字段
public class LinkedBlockingQueue<E> extends AbstractQueue<E>
implements BlockingQueue<E>, java.io.Serializable {
//节点
static class Node<E> {
//存储元素
E item;
?
//下一个节点
Node<E> next;
//...
}
?
//容量上限
private final int capacity;
?
//队列元素数量
private final AtomicInteger count = new AtomicInteger();
?
//头节点
transient Node<E> head;
?
//尾节点
private transient Node<E> last;
?
//出队的锁
private final ReentrantLock takeLock = new ReentrantLock();
?
//出队的等待队列
private final Condition notEmpty = takeLock.newCondition();
?
//入队的锁
private final ReentrantLock putLock = new ReentrantLock();
?
//入队的等待队列
private final Condition notFull = putLock.newCondition();
}
从字段中,我们可以知道它使用单向链表的节点、且用首尾节点记录队列的头尾,并且它使用两把锁、两个等待队列作用于队头、尾,与ArrayBlocki