ArrayBlockingQueue:基于数组的有界队列¶
一、是什么¶
基于数组的有界阻塞队列,必须指定容量。
二、结构¶
- 数组 items。
- putIndex:下一个写位置。
- takeIndex:下一个读位置。
- count:当前元素数。
三、单锁设计¶
和 LinkedBlockingQueue 不同,ArrayBlockingQueue 用一个 ReentrantLock:
public class ArrayBlockingQueue<E> {
final Object[] items;
int takeIndex;
int putIndex;
int count;
final ReentrantLock lock;
private final Condition notEmpty;
private final Condition notFull;
}
读和写共用一把锁,所以读写互斥。
四、put 流程¶
public void put(E e) throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == items.length)
notFull.await();
enqueue(e);
} finally {
lock.unlock();
}
}
private void enqueue(E x) {
items[putIndex] = x;
if (++putIndex == items.length) putIndex = 0; // 循环
count++;
notEmpty.signal();
}
五、为什么用单锁¶
- 数组实现简单,读写在同一个数组上,双锁很难实现。
- 性能不如 LinkedBlockingQueue,但内存开销小(没有 Node 对象)。
六、公平性可选¶
公平锁按等待顺序,吞吐低。
七、对比 LinkedBlockingQueue¶
| ArrayBlockingQueue | LinkedBlockingQueue | |
|---|---|---|
| 锁 | 单锁 | 读写双锁 |
| 读写并行 | ❌ | ✅ |
| 内存 | 连续数组 | Node 对象 |
| 容量 | 必须指定 | 默认无界 |
| GC | 无额外对象 | 有 Node |
怎么选
- 吞吐优先:LinkedBlockingQueue。
- 内存敏感、容量固定:ArrayBlockingQueue。