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 会无限制创建线程的原因。
相关推荐
无心水17 分钟前
深入Java线程池:BlockingQueue实现全景解析与实战指南
java·后端·面试
Java水解18 分钟前
Rust 性能优化实战:从 unsafe 使用到 SIMD 指令,让服务端响应快 2 倍
后端·rust
Java水解21 分钟前
JAVA面试题大全(200+道题目)
java·后端·面试
卷福同学30 分钟前
AI浏览器comet拉新,一单20美元(附详细教程)
人工智能·后端
大鱼七成饱44 分钟前
掌握 anyhow,让你的 Rust 错误处理优雅又安全
后端·rust
2301_772093561 小时前
高并发webserver_interview
运维·服务器·数据库·后端·网络协议·mysql·wireshark
HashTang1 小时前
不用再配服务器了!这套 Next.js + Cloudflare 模板,一个人搞定全栈出海
前端·后端·边缘计算
水淹萌龙3 小时前
玩转 Go 表达式引擎:expr 实战指南
开发语言·后端·golang
Yeats_Liao4 小时前
Go Web 编程快速入门 07.4 - 模板(4):组合模板与逻辑控制
开发语言·后端·golang
咖啡教室4 小时前
每日一个计算机小知识:MAC地址
后端·网络协议