ArrayBlockingQueue 源码

核心变量

java 复制代码
public class ArrayBlockingQueue<E> extends AbstractQueue<E>
        implements BlockingQueue<E>, java.io.Serializable {

    // 底层存储:定长数组,一旦初始化容量不可扩容
    final Object[] items;

    // 出队索引:take/poll 取元素位置
    int takeIndex;

    // 入队索引:put/offer 添加元素位置
    int putIndex;

    // 当前队列元素总数
    int count;

    // 全局独占锁:所有入队、出队操作共用一把锁(核心特性!单锁)
    final ReentrantLock lock;

    // 非空条件:队列有元素时唤醒消费者
    private final Condition notEmpty;

    // 非满条件:队列有空位时唤醒生产者
    private final Condition notFull;
}

构造方法

  • 数组固定容量,无扩容机制,满了就阻塞 / 抛异常
  • 入队、出队、查询全部竞争同一把 ReentrantLock
java 复制代码
// 1. 基础构造:指定容量,默认非公平锁
public ArrayBlockingQueue(int capacity) {
    this(capacity, false);
}

// 2. 完整构造:容量 + 是否公平锁
public ArrayBlockingQueue(int capacity, boolean fair) {
    if (capacity <= 0)
        throw new IllegalArgumentException();
    // 初始化定长数组,容量固定
    items = new Object[capacity];
    // 创建可重入锁,fair=true公平,false非公平(默认)
    lock = new ReentrantLock(fair);
    // 绑定两个条件变量,共用同一把lock
    notEmpty = lock.newCondition();
    notFull = lock.newCondition();
}

// 3. 带集合初始化的构造
public ArrayBlockingQueue(int capacity, boolean fair, Collection<? extends E> c) {
    this(capacity, fair);
    // 加锁批量导入集合元素
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        int i = 0;
        for (E e : c) {
            checkNotNull(e);
            items[i++] = e;
        }
        count = i;
        putIndex = (i == capacity) ? 0 : i;
    } finally {
        lock.unlock();
    }
}

入队方法

add

  • 调用 offer,失败直接抛队列满异常,不阻塞
java 复制代码
public boolean add(E e) {
    // 调用父类AbstractQueue的add
    return super.add(e);
}
// AbstractQueue.add
public boolean add(E e) {
    if (offer(e))
        return true;
    else
        throw new IllegalStateException("Queue full");
}

offer(不超时)

  • 加锁,队列满直接返回 false,不阻塞
java 复制代码
public boolean offer(E e) {
    checkNotNull(e); // 不允许null元素
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        // 判断队列未满才入队
        if (count == items.length)
            return false;
        else {
            enqueue(e);
            return true;
        }
    } finally {
        lock.unlock();
    }
}

offer(超时)

java 复制代码
public boolean offer(E e, long timeout, TimeUnit unit)
        throws InterruptedException {
    checkNotNull(e);
    long nanos = unit.toNanos(timeout);
    final ReentrantLock lock = this.lock;
    // 可中断加锁
    lock.lockInterruptibly();
    try {
        // 队列满,循环等待超时
        while (count == items.length) {
            if (nanos <= 0)
                return false;
            // 生产者等待notFull,释放锁,超时唤醒
            nanos = notFull.awaitNanos(nanos);
        }
        enqueue(e);
        return true;
    } finally {
        lock.unlock();
    }
}

put

java 复制代码
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

  • 环形数组,putIndex 循环 0 ~ (length - 1)
java 复制代码
private void enqueue(E x) {
    // putIndex位置放入元素
    final Object[] items = this.items;
    items[putIndex] = x;
    // 环形数组:到末尾重置索引为0
    if (++putIndex == items.length)
        putIndex = 0;
    count++;
    // 放入元素后,唤醒一个阻塞的消费者
    notEmpty.signal();
}

对比

方法 队列满时的动作 返回值 是否阻塞
add(e) 直接失败 抛 IllegalStateException 不阻塞
offer(e) 直接失败 return false 不阻塞
put(e) 阻塞等待空位 无返回 无限阻塞,可中断(notFull.await)
offer(e,time,unit) 限时阻塞 超时返回 false 限时阻塞(notFull.awaitNanos)