synchronousqueue 是一个不存储元素的阻塞队列,实现无缓冲直传语义,内部容量为0,put()和take()操作必须配对阻塞等待,适用于线程池直接交接或生产者-消费者严格同步场景。

SynchronousQueue 是 Java 并发包(java.util.concurrent)中一个特殊的阻塞队列,它**不存储元素**,每个插入操作必须等待另一个线程的移除操作,反之亦然。它实现的是“**无缓冲直传**”语义——生产者线程直接把任务 handed off(移交)给消费者线程,中间不经过任何队列暂存。
为什么说它是“无缓冲直传”?
它内部没有容量(capacity = 0),不能容纳任何待处理元素。调用 put() 会阻塞,直到有其他线程调用 take();调用 take() 同样阻塞,直到有其他线程调用 put()。这种“一手交、一手接”的协作机制,天然适合需要严格同步交接的场景,比如工作窃取、线程池中的直接交接策略。
典型用法:配合 ThreadPoolExecutor 实现直接交接
最常见且实用的场景是作为线程池的阻塞队列,启用“直接交接”策略:
- 使用
new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime, unit, new SynchronousQueue())
- 当新任务提交时,若核心线程空闲,任务立即交给空闲线程执行;
- 若无空闲核心线程,线程池会尝试创建新线程(不超过 maxPoolSize);
- 如果已达最大线程数,且无空闲线程,则触发拒绝策略(因为 SynchronousQueue 拒绝入队)。
这避免了任务在队列中排队等待,实现了“来了就交、有人就干”的低延迟直传模型。
手动使用:生产者-消费者配对协作
可显式用两个线程模拟 handoff:
- 生产者调用
queue.put(item) → 阻塞,直到消费者调用 <code>queue.take(); - 消费者调用
queue.take()→ 阻塞,直到生产者调用queue.put(item); - 一旦匹配成功,数据直接从生产者线程内存“移交”到消费者线程,不复制、不缓存。
注意:SynchronousQueue 支持公平模式(FIFO 交接顺序)和非公平模式(默认,类似栈,后进先交),可通过构造函数指定:new SynchronousQueue(true) 启用公平模式。
使用注意事项
它不是万能的,需谨慎选择:
- 不适合高吞吐、异步解耦场景(因无缓冲,容易导致线程频繁阻塞);
- 务必确保生产与消费节奏大致匹配,否则易出现线程长时间挂起;
- 不能调用
peek()或size()获取状态(始终返回 null / 0); - 迭代器为空,不支持批量操作(如
addAll)。
它的价值在于强制线程间同步协作,而非缓存或解耦——用对了,就是轻量高效的“握手通道”。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











