java详解常用的阻塞队列,详解java中的阻塞队列

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 阻塞队列的资料请关注脚本之家其它相关文章!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值