java+arrayblockquene_Java源码分析-ArrayBlockingQueue

ArrayBlockingQueue是JDK1.5开始concurrent包中提供的并发工具类,是一个基于数组的有界的先进先出队列,如果加入元素时,数组已满,或数组为空时,取元素都会阻塞当前线程,是一个典型的生产者消费者模式。类似的类还有LinkedBlockingQueue,PriorityBlockingQueue。

继承关系

public class ArrayBlockingQueue extends AbstractQueue

implements BlockingQueue, java.io.Serializable

public interface BlockingQueue extends Queue

核心成员变量

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; //队中元素计数

/*

* Concurrency control uses the classic two-condition algorithm

* found in any textbook.

*/

/** Main lock guarding all access */

final ReentrantLock lock; //可重入锁

/** Condition for waiting takes */

private final Condition notEmpty; //条件变量

/** Condition for waiting puts */

private final Condition notFull; //条件变量

构造方法

public ArrayBlockingQueue(int capacity, boolean fair) {

if (capacity <= 0)

throw new IllegalArgumentException();

this.items = new Object[capacity]; //初始化指定大小的有界队列

lock = new ReentrantLock(fair); //fair指示该锁是否是公平的

notEmpty = lock.newCondition();

notFull = lock.newCondition();

}

添加元素:put方法

public void put(E e) throws InterruptedException {

checkNotNull(e);

final ReentrantLock lock = this.lock;

lock.lockInterruptibly();

try {

while (count == items.length)

notFull.await(); //添加元素时,如果已满,则阻塞当前线程,等待在notFull这个条件变量上,等待notFull调用signal唤醒

enqueue(e); //此时队列肯定未满

} finally {

lock.unlock();

}

}

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加1,如果到达数组尾部,则从0开始

putIndex = 0;

count++; //增加计数

notEmpty.signal(); //增加一个元素后,如果有线程等待在noEmpty条件变量上,通知并唤醒一种一个线程。

}

put方法首先判断队列是否已满,如果已满,则阻塞当前线程,等待在notFull这个条件变量上,等待notFull调用signal唤醒。当队列非空时,将该元素加入队尾,增加元素计数,唤醒因为进行去操作时数组为空而等待在notEmpty上的线程,通知它此时队列已经有元素了,你可以进行取操作了。

取元素:take方法

public E take() throws InterruptedException {

final ReentrantLock lock = this.lock;

lock.lockInterruptibly();

try {

while (count == 0)

notEmpty.await(); //取元素但是队列为空时,阻塞线程,等待在notEmpty上

return 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;

if (++takeIndex == items.length)

takeIndex = 0;

count--; //计数减1

if (itrs != null)

itrs.elementDequeued();

notFull.signal(); //通知因为添加元素但是队列已满时而阻塞的线程,队列此时可插入了

return x; //返回队头元素

}

take方法和put方法类似,先检查队列是否为空,队列为空时,阻塞线程,等待在notEmpty上。当队列非空时,进行出队操作。同时还要通知因为添加元素但是队列已满时而阻塞的线程,队列此时可插入了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值