synchronousqueue不存储元素,因其容量为0,put与take必须配对阻塞完成“手递手”交付,实现无缓冲、零拷贝、严格同步的线程间数据交换。

SynchronousQueue 是 Java 并发包(java.util.concurrent)中一种特殊的阻塞队列,它**不存储元素**,每个插入操作必须等待另一个线程的对应移除操作,反之亦然。它本质上是“一对一”传递的同步通道,适合用于线程间直接交接任务,常作为 Executors.newCachedThreadPool() 的默认工作队列。
为什么说它“不存储元素”?
它的内部没有容量缓冲空间:当你调用 put(e) 时,若无其他线程正在调用 take(),当前线程会阻塞;同理,take() 也会一直等待直到有线程执行 put()。它不保留任何待处理的元素,所有元素必须“即时交接”。这与 ArrayBlockingQueue 或 LinkedBlockingQueue 有明显区别。
基本使用方式:put/take 配对
最典型的用法是生产者-消费者线程通过 put() 和 take() 进行严格同步:
- 生产者线程调用
queue.put(item)→ 阻塞,直到消费者调用take() - 消费者线程调用
queue.take()→ 阻塞,直到生产者调用put(item) - 一旦匹配成功,元素直接从生产者传给消费者,不经过队列内部存储
支持超时和非阻塞操作
除了阻塞式 put/take,还可使用带超时或轮询的方法避免无限等待:
-
offer(e, timeout, unit):尝试插入,超时未匹配则返回false -
poll(timeout, unit):尝试获取,超时无数据则返回null -
offer(e)和poll()(无参):非阻塞,立即返回true/false或null,仅在对方线程恰好就绪时才成功
实际应用场景示例
常见于需要严格配对协作的场景:
- 线程池中为每个新任务分配一个空闲线程(
CachedThreadPool就靠它实现“按需创建+快速交接”) - 主控线程向工作线程委派单个任务,并等待结果(配合
FutureTask或自定义响应机制) - 模拟“握手式”通信:比如 A 线程必须等 B 线程准备好后才交付参数,B 也必须等 A 发来指令才开始执行
不复杂但容易忽略:SynchronousQueue 的核心价值不在“队列”,而在“同步点”。用它时,要确保两端线程逻辑能自然形成配对,否则容易因单方面阻塞导致程序挂起。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











