ArrayBlockingQueue 源码阅读与分析

ArrayBlockingQueue 源码阅读与分析

通过这个类的名字,可以知道ArrayBlockingQueue是一个底层使用数组实现,具有队列特点的先进先出以及线程安全的一个集合类,他还可以实现指定时间的阻塞读写,也就是可以解决生产者消费者问题的阻塞队列。

首先来看一下它的构造方法:

public ArrayBlockingQueue(int capacity) {

this(capacity, false);

}

public ArrayBlockingQueue(int capacity, boolean fair) {

if (capacity <= 0)

throw newIllegalArgumentException();

this.items = newObject[capacity];

lock = newReentrantLock(fair);

notEmpty =lock.newCondition();

notFull = lock.newCondition();

}

这是前两个构造方法,可以发现一个问题,就是它没有默认构造器,传入的参数即为创建的对象数组的大小,同时初始化锁和这个锁上的两个Condition,一个为 notEmpty,用作队列空时,进行take操作的等待;另一个为notFull,作用是队列满时,put操作的等待。

首先来看一下offer方法,offer方法有两个重载的实现, 用于插入元素至数组的尾部。

先看一下不带参数的offer方法:

lock.lock();

try {

if (count ==items.length)

return false;

else {

insert(e);

return true;

}

} finally {

lock.unlock();

}

其中的count是队列中的元素的个数,items就是存值的数组,在数组满的情况下则不进入等待,而是直接返回 false。不满的情况下,会进入insert方法,会执行notEmpty.signal();,唤醒再队列为空时take操作等待的线程

它还有一个有三个参数的重载方法,如数组已满,则进入等待,直到以下三种情况时才继续:被唤醒、到达指定的时间或当前线程被中断(interrupt)。此方法首先将指定的时间转换为纳秒,然后执行加锁操作,如数组未满,则将对象插入数组,如数组已满,且已超过指定的时间,则返回 false;如未超过指定的时间,则调用 notFull condition 的 awaitNanos 方法进行等待,如为被唤醒或超时,则继续判断数组是否已满;如线程被 interrupt,则直接抛出 InterruptedException。

再来看一下put 方法

具体的代码如下:

public void put(E e) throwsInterruptedException {

checkNotNull(e);

final ReentrantLock lock = this.lock;

lock.lockInterruptibly();

try {

while (count == items.length)

notFull.await();

insert(e);

} finally {

lock.unlock();

}

}

可以看到,这个方法在数组已满的情况下会一直等待,直到数组不为空或线程被 interrupt。

接下来再来看一下poll方法,此方法用于获取队列中的第一个元素。和offer一样,也有两个重载。

public E poll() {

final ReentrantLocklock = this.lock;

lock.lock();

try {

return (count ==0) ? null : extract();

} finally {

lock.unlock();

}

}

如若今生再相见,哪怕流离百世,迷途千年,也愿。

ArrayBlockingQueue 源码阅读与分析

相关文章:

你感兴趣的文章:

标签云: