BlockingQueue与SynchronousQueue

BlockingQueue

BlockingQueue 是一个支持阻塞操作 的队列接口,位于 java.util.concurrent 包中。它的典型应用就是生产者-消费者模型

需要首先给队列设置容量

BlockingQueue<String> queue = new ArrayBlockingQueue<>(3); // 容量=3

BlockingQueue 的四组 API

1. 抛异常

  • 当队列满时,再 add() 会抛异常;
  • 当队列空时,再 remove() 会抛异常。
scss 复制代码
add(e)       // 插入元素,成功返回 true,满时抛 IllegalStateException
remove()     // 移除队首元素,空时抛 NoSuchElementException
element()    // 查看队首元素,空时抛 NoSuchElementException

2. 返回特殊值

  • 满了插入失败返回 false
  • 空了移除失败返回 null
scss 复制代码
offer(e)     // 插入元素,成功返回 true,满时返回 false
poll()       // 移除队首元素,空时返回 null
peek()       // 查看队首元素,空时返回 null

3. 一直阻塞

  • 满了 put() 会一直阻塞,直到队列有空间;
  • 空了 take() 会一直阻塞,直到队列有元素。
scss 复制代码
put(e)       // 插入元素,满时阻塞
take()       // 移除并返回队首元素,空时阻塞

4.超时退出

  • 满了 offer(e, time, unit) 会等待指定时间,超时返回 false
  • 空了 poll(time, unit) 会等待指定时间,超时返回 null
scss 复制代码
offer(e, 2, TimeUnit.SECONDS)   // 等待 2 秒插入,失败返回 false
poll(2, TimeUnit.SECONDS)       // 等待 2 秒取出,失败返回 null
操作类型 抛异常 特殊值 阻塞 超时
插入 add(e) offer(e) put(e) offer(e, time, unit)
移除 remove() poll() take() poll(time, unit)
检查队首 element() peek() ------ ------

适合场景

  • 抛异常:适合严格要求,必须处理异常的场景。
  • 返回特殊值:适合可以容忍失败的场景。
  • 阻塞:适合生产者-消费者模型,不急着返回,等资源可用。
  • 超时:适合对实时性有要求的场景,不能无限等待。

SynchronousQueue

SynchronousQueue 是 Java 并发包里一个 非常特殊的 BlockingQueue 。它和其他 BlockingQueue(如 ArrayBlockingQueueLinkedBlockingQueue)不一样,它的容量永远是 0,没有任何内部缓冲。

特点

  1. 容量为 0
    • 不能存放任何元素。
    • put() 一个元素时,必须有另一个线程正在 take(),否则会阻塞。
    • take() 时也必须有线程 put(),否则也会阻塞。
  1. 一手交钱一手交货
    • 类似一个"当面交易"的模型。
    • 生产者线程和消费者线程必须同时到场,才能完成元素的交接。
  1. 线程间直接传递数据
    • 没有缓存区,数据不存储,而是 直接在两个线程之间传递

API 行为

  • put(e):如果没有消费者在等待,阻塞。
  • take():如果没有生产者在等待,阻塞。
  • offer(e, timeout, unit):在超时时间内,如果有消费者等待就成功,否则返回 false
  • poll(timeout, unit):在超时时间内如果有生产者等待就取到数据,否则返回 null

使用场景

  1. 线程间直接交换消息
    • 两个线程需要强同步(例如生产者和消费者一对一交接)。
  1. 线程池的工作队列(Executors.newCachedThreadPool 默认使用它)
    • 因为 SynchronousQueue 不存储任务,提交的任务必须马上被某个线程取走执行,如果没有空闲线程,就创建新线程。
    • 这也是为什么 CachedThreadPool 会无限制创建线程的原因。
相关推荐
前端伪大叔2 小时前
第15篇:Freqtrade策略不跑、跑错、跑飞?那可能是这几个参数没配好
前端·javascript·后端
Postkarte不想说话2 小时前
使用MSF生成反弹shell
后端
golang学习记2 小时前
Go 项目目录结构最佳实践:少即是多,实用至上
后端
合作小小程序员小小店2 小时前
web开发,在线%校园,论坛,社交管理%系统,基于html,css,python,django,mysql
数据库·后端·mysql·django·web app
用户4099322502122 小时前
PostgreSQL里的PL/pgSQL到底是啥?能让SQL从“说目标”变“讲步骤”?
后端·ai编程·trae
红烧code3 小时前
【Rust GUI开发入门】编写一个本地音乐播放器(9. 制作设置面板)
开发语言·后端·rust
你三大爷3 小时前
Safepoint的秘密探寻
java·后端
福大大架构师每日一题3 小时前
2025-10-02:不同 XOR 三元组的数目Ⅰ。用go语言,给你一个长度为 n 的数组 nums,数组恰好包含 1 到 n 这 n 个整数(每个数出现一次)
后端
王嘉俊9254 小时前
Django 入门:快速构建 Python Web 应用的强大框架
前端·后端·python·django·web·开发·入门