👋hi,我不是一名外包公司的员工,也不会偷吃茶水间的零食,我的梦想是能写高端CRUD
🔥 2025本人正在沉淀中... 博客更新速度++
👍 欢迎点赞、收藏、关注,跟上我的更新节奏
📚欢迎订阅专栏,专栏名《在2B工作中寻求并发是否搞错了什么》
什么是ArrayBlockingQueue
ArrayBlockingQueue
是 Java 并发编程中一个基于数组实现的有界阻塞队列,属于 java.util.concurrent
包,实现了 BlockingQueue
接口。
具有以下特性:
有界性
- 队列容量在创建时固定,无法动态扩容(必须显式指定初始容量)。
- 适合需要控制资源使用的场景,避免无限制增长导致内存溢出。
线程安全
- 内部通过 ReentrantLock 保证并发操作的安全性。
- 采用"单锁双条件"(一个锁管理入队和出队条件)实现同步。
阻塞操作
- 队列满时:put(e) 方法会阻塞,直到有空间可用。
- 队列空时:take() 方法会阻塞,直到有新元素加入。
FIFO 原则
- 元素按先进先出顺序处理,保证公平性。
使用ArrayBlockingQueue
构造方法

java
// 指定容量(必须)
ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
// 指定容量和公平性(true 表示公平锁)
ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10, true);
// 指定容量、公平性,并初始化集合
List<Integer> list = Arrays.asList(1, 2, 3);
ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10, true, list);
阻塞使用(put、take)
put(E e)方法: 阻塞当前线程生产(往队列中塞数据)
java
// 生产者线程
new Thread(() -> {
try {
for (int i = 0; i < 5; i++) {
queue.put(i); // 队列满时阻塞
System.out.println("生产: " + i);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
take()方法: 阻塞当前线程消费(往队列里面取数据)。
java
// 消费者线程
new Thread(() -> {
try {
while (true) {
Integer value = queue.take(); // 队列空时阻塞
System.out.println("消费: " + value);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
非阻塞方法使用(offer、poll)
offer(E e)方法:尝试插入,队列满时直接返回 false。
java
boolean success = queue.offer(100);
System.out.println("插入是否成功: " + success);
poll()方法:尝试取出,队列空时返回 null。
java
Integer value = queue.poll();
System.out.println("取出值: " + value);
不建议使用的非阻塞方法(add、remove、element)
add和element这种方法,会直接抛出异常。
add(E e): 向阻塞队列放入元素,阻塞队列满的话,直接抛出IllegalStateException
异常。
java
ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(1); // 容量为1
queue.add(10); // 成功插入
try {
queue.add(20); // 队列已满,抛出 IllegalStateException
} catch (IllegalStateException e) {
System.out.println("队列已满,add() 抛异常: " + e);
}
// AbstractQueue#add
// 抛出IllegalStateException异常
public boolean add(E e) {
if (offer(e))
return true;
else
throw new IllegalStateException("Queue full"); // 阻塞队满,抛出异常
}
elemet(): 向阻塞队列获取元素,阻塞队列为空的话,直接抛出NoSuchElementException
异常。
java
ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(1); // 空队列
try {
Integer head = queue.element(); // 队列为空,抛出 NoSuchElementException
} catch (NoSuchElementException e) {
System.out.println("队列为空,element() 抛异常: " + e);
}
// AbstractQueue#element
public E element() {
E x = peek();
if (x != null)
return x;
else
throw new NoSuchElementException(); // 阻塞队列为空,抛出异常
}
remove(): 删除阻塞队列的头元素,并返回这个头元素。如果阻塞队列为空,直接抛出NoSuchElementException
异常。
java
ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(1); // 空队列
queue.remove(); // NoSuchElementException异常
public E remove() {
E x = poll();
if (x != null)
return x;
else
throw new NoSuchElementException(); // 阻塞队列为空,抛出异常
}
超时阻塞使用(offer、poll)
也是offer方法,只是多传了时间相关的参数。
offer(e, time, unit): 等待time秒后,插入数据,返回执行结果。
java
// 生产者等待2秒插入
boolean success = queue.offer(200, 2, TimeUnit.SECONDS);
poll(time, unit) :等待time秒后获取数据,队列为空的话,返回null。
java
// 消费者等待3秒取出
Integer value = queue.poll(3, TimeUnit.SECONDS);
后话
主播这么快又结束了?没有的!宝子,还有呢!
关注点给主播点上,下一篇主播给大家表演看源码。