【Java并发】【ArrayBlockingQueue】适合初学体质的ArrayBlockingQueue入门

👋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);

后话

主播这么快又结束了?没有的!宝子,还有呢!

关注点给主播点上,下一篇主播给大家表演看源码。

相关推荐
不倒翁玩偶14 分钟前
IDEA导入新的SpringBoot项目没有启动按钮
java·spring boot·intellij-idea
小小小米粒29 分钟前
Maven Tools
java
苏三说技术31 分钟前
xxl-job 和 elastic-job,哪个更好?
后端
三小河39 分钟前
Agent Skill与Rules的区别——以Cursor为例
前端·javascript·后端
kali-Myon43 分钟前
2025春秋杯网络安全联赛冬季赛-day1
java·sql·安全·web安全·ai·php·web
我是咸鱼不闲呀1 小时前
力扣Hot100系列20(Java)——[动态规划]总结(下)( 单词拆分,最大递增子序列,乘积最大子数组 ,分割等和子集,最长有效括号)
java·leetcode·动态规划
三小河1 小时前
前端视角详解 Agent Skill
前端·javascript·后端
清水白石0081 小时前
深入解析 LRU 缓存:从 `@lru_cache` 到手动实现的完整指南
java·python·spring·缓存
牛奔1 小时前
Go 是如何做抢占式调度的?
开发语言·后端·golang
颜酱1 小时前
二叉树遍历思维实战
javascript·后端·算法