本文主要是介绍ArrayBlockingQueue浅析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
基于数组的阻塞队列实现,在ArrayBlockingQueue内部,维护了一个定长数组,以便缓存队列中的数据对象,这是一个常用的阻塞队列,除了一个定长数组外,
ArrayBlockingQueue内部还保存着两个整形变量,分别标识着队列的头部和尾部在数组中的位置。
public class ArrayBlockingQueue<E> extends AbstractQueue<E>
implements BlockingQueue<E>, java.io.Serializable {
// 保存元素的数组
final Object[] items;
//元素的个数
int count;
// 取元素的下标(头部)
int takeIndex;
// 存元素的下标(尾部)
int putIndex;
// 锁(默认syn也是非公平锁)
final ReentrantLock lock;
// 取元素等待 Condition 能够更加精细的控制多线程的休眠与唤醒。对于同一个锁,我们可以创建多个Condition,在不同的情况下使用不同的Condition。
private final Condition notEmpty;
// 添加元素等待
private final Condition notFull;
//内部是数组初始化要指定数组的长度
public ArrayBlockingQueue(int capacity) {
this(capacity, false);// 默认是非公平锁
}
// 最终要调用的构造方法
public ArrayBlockingQueue(int capacity, boolean fair) {
if (capacity <= 0)
throw new IllegalArgumentException();
this.items = new Object[capacity];
lock = new ReentrantLock(fair);
notEmpty = lock.newCondition();
notFull = lock.newCondition();
}
// 向队列尾部添加元素
public boolean offer(E e) {
checkNotNull(e);// 元素为空直接NPE
final ReentrantLock lock = this.lock;
lock.lock();// 加锁
try {
if (count == items.length)// 当前队列是否已满
return false; //有界队列满了不添加直接返回false
else {
enqueue(e);//有空闲直接加入队列 返回true
return true;
}
} finally {
lock.unlock();// 解锁
}
}
private void enqueue(E x) {
final Object[] items = this.items;
items[putIndex] = x;// 元素入队
if (++putIndex == items.length)// 下一个入队的下标
putIndex = 0;
count++;// 元素个数
notEmpty.signal();// 唤醒取元素的等待线程
}
// 向尾部添加数据
public void put(E e) throws InterruptedException {
checkNotNull(e);// 元素为空直接NPE
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();// 加锁(可中断的)
try {
while (count == items.length)// 当前队列是否已满
notFull.await();//一直等到数组有空闲
enqueue(e);// 元素入队
} finally {
lock.unlock();
}
}
// 从头部获取并移除一个元素
public E poll() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return (count == 0) ? null : dequeue();// 如果队列为空返回null
} finally {
lock.unlock();
}
}
private E dequeue() {
final Object[] items = this.items;
E x = (E) items[takeIndex]; //获取元素
items[takeIndex] = null; // 将数据获取元素位置置为null 移除元素
if (++takeIndex == items.length)
takeIndex = 0;
count--;
if (itrs != null)
itrs.elementDequeued();
notFull.signal();
return x;
}
// 从头部获取并移除一个元素
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0)
notEmpty.await();//如果队列为空就一直等待直到队列有数据存入然后获取数据
return dequeue();
} finally {
lock.unlock();
}
}
// 获取元素但是不移除元素
public E peek() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return itemAt(takeIndex);
} finally {
lock.unlock();
}
}
final E itemAt(int i) {
return (E) items[i];
}
//获取数组的大小
public int size() {
final ReentrantLock lock = this.lock;//这里有加锁的操作 但是并没有对count做修改
lock.lock(); // 如果count声明voliate 这里可以不加锁
try {
return count;
} finally {
lock.unlock();
}
}
}
这篇关于ArrayBlockingQueue浅析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!