public class ArrayBlockingQueue extends AbstractQueue
implements BlockingQueue, java.io.Serializable {
#zs#* The queued items #fzs#
//以数组的结构存储队列的元素,采用的是循环数组
final Object[] items;
#zs#* items index for next take, poll, peek or remove #fzs#
//队列的队头索引
int takeIndex;
#zs#* items index for next put, offer, or add #fzs#
//队列的队尾索引
int putIndex;
#zs#* Number of elements in the queue #fzs#
//队列中元素的个数
int count;
#zs#* Main lock guarding all access #fzs#
//对于ArrayBlockingQueue所有的操作都需要加锁,
final ReentrantLock lock;
#zs#* Condition for waiting takes #fzs#
//条件队列,当队列为空时阻塞消费者并在生产者生产后唤醒消费者
private final Condition notEmpty;
#zs#* Condition for waiting puts #fzs#
//条件队列,当队列满时阻塞生产者,并在消费者消费队列后唤醒生产者
private final Condition notFull;
}
根据类的定义字段可以看到,有两个Condition条件队列,猜测以下过程
当队列为空,消费者试图消费时应该调用notEmpty.await()方法阻塞,并在生产者生产后调用notEmpty.single()方法
当队列已满,生产者试图放入元素应调用notFull.await()方法阻塞,并在消费者消费队列后调用notFull.single()方法向队
向队列中添加元素put()方法的添加过程。
#zs#*
* 向队列中添加元素
* 当队列已满时需要阻塞当前线程
* 放入元素后唤醒因队列为空阻塞的消费者
#fzs#
public void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
//当队列已满时需要notFull.await()阻塞当前线程
//offer(e,time,unit)方法就是阻塞的时候加了超时设定
while (count == items.length)
notFull.await();
//放入元素的过程
enqueue(e);
} finally {
lock.unlock();
}
}
#zs#*enqueue实际添加元素的方法#fzs#
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();
}
从队列中获取元素take()方法的获取过程。
#zs#*
* 从队列中获取元素
* 当队列已空时阻塞当前线程
* 从队列中消费元素后唤醒等待的生产线程
#fzs#
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
//队列为空需要阻塞当前线程
while (count == 0)
notEmpty.await();
//获取元素的过程
return dequeue();
} finally {
lock.unlock();
}
}
#zs#*dequeue实际消费元素的方法#fzs#
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;
}
总结
阻塞队列提供了不同于普通队列的增加、删除元素的方法,核心在与队列满时阻塞生产者和队列空时阻塞消费者。
这一阻塞过程依靠与锁绑定的Condition对象实现。Condition接口的实现在AQS中实现,具体的实现类是
ConditionObject
以上就是详解java中的阻塞队列的详细内容,更多关于java 阻塞队列的资料请关注脚本之家其它相关文章!