ArrayBlockingQueue 通过一个全局锁和两个条件变量实现了一个标准的生产者消费者模型。
用法
package test;
import java.util.concurrent.ArrayBlockingQueue;
public class TestArrayBlockingQueue {
public static void main(String[] args) throws InterruptedException {
ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue(8);
queue.put(1);
System.out.println("queue.take() = " + queue.take());
System.out.println("queue.contains(1) = " + queue.contains(1));
}
}
实现原理
核心变量
// 保存队列元素的数组
final Object[] items;
// 获取元素的索引下标
int takeIndex;
// 添加元素的索引的下标
int putIndex;
// items 数组中有效元素个数
int count;
// 全局锁
final ReentrantLock lock;
// 用于等待 items 数组非空
private final Condition notEmpty;
// 用于等待 items 数组非满
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);
// 创建等待数组非空条件变量
notEmpty = lock.newCondition();
// 创建等待数组非满条件变量
notFull = lock.newCondition();
}
put(E e)
public void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
// 可中断获取互斥锁
lock.lockInterruptibly();
try {
// 如果队列满了,当前线程开始等待,条件为 notFull
while (count == items.length)
notFull.await();
// 队列未满则添加到队列中
enqueue(e);
} finally {
// 释放锁
lock.unlock();
}
}
enqueue(E x)
private void enqueue(E x) {
final Object[] items = this.items;
// 将元素放到数组下标为 putIndex 的位置
items[putIndex] = x;
// putIndex+1 后若到达了数组末尾,就将 putIndex 从 0 开始。
if (++putIndex == items.length)
putIndex = 0;
// 数组中元素个数+1
count++;
// 唤醒等待在非空条件的线程
notEmpty.signal();
}
take()
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
// 可中断获取锁
lock.lockInterruptibly();
try {
// 队列中没有元素时等待
while (count == 0)
notEmpty.await();
// 从队列中获取一个元素
return dequeue();
} finally {
lock.unlock();
}
}
dequeue()
private E dequeue() {
final Object[] items = this.items;
// 获取 takeIndex 下标的元素
E x = (E) items[takeIndex];
items[takeIndex] = null;
// 当 takeIndex 下标达到数组长度时,回退到 0
if (++takeIndex == items.length)
takeIndex = 0;
// 可用元素数量 -1
count--;
// 更新迭代器
if (itrs != null)
itrs.elementDequeued();
// 唤醒等待队列为非满的线程
notFull.signal();
return x;
}
contains(Object o)
public boolean contains(Object o) {
// 非空校验
if (o == null) return false;
final Object[] items = this.items;
final ReentrantLock lock = this.lock;
// 获取锁
lock.lock();
try {
// 队列中元素个数大于 0
if (count > 0) {
final int putIndex = this.putIndex;
// 从 takeIndex 下标处开始查找
int i = takeIndex;
do {
if (o.equals(items[i]))
return true;
if (++i == items.length)
i = 0;
} while (i != putIndex); // 当 takeIndex 追上 putIndex 时,退出循环rto
}
return false;
} finally {
lock.unlock();
}
}