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

后话

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

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

相关推荐
骄马之死4 小时前
SpringMVC + SpringBoot 核心知识点总结
java·spring boot·后端
GoGeekBaird5 小时前
Anthropic技能"(Skills)的经验分享
后端
王码码20356 小时前
多台服务器怎么统一看状态?Beszel 轻量监控,搭起来不费事
运维·服务器·后端·安全·阿里云·接口·web
郑洁文6 小时前
基于Spring Boot的流浪动物救助网站
java·spring boot·后端·毕设·流浪动物救助
螺丝钉code7 小时前
JAVA项目 Claude code CLAUDE.md 到底应该怎么写
java·人工智能·claude code
指令集梦境7 小时前
Cursor + Spring Boot实战:从零写一个RESTful API
spring boot·后端·restful
摇滚侠8 小时前
Maven 入门+高深 单一架构案例 54-59
java·架构·maven·intellij-idea
VidDown8 小时前
Webhook 调试器:让第三方回调“原形毕露”
java·开发语言·javascript·编辑器·postman
码云之上8 小时前
聊聊如何设计一个高效、稳定的 Node.js 接入层
前端·后端·node.js
折哥的程序人生 · 物流技术专研8 小时前
Java 23 种设计模式:从踩坑到精通 | 原型模式 —— 克隆对象,深拷贝与浅拷贝的坑你踩过吗?
java·设计模式·架构·原型模式·单一职责原则