synchronousqueue 是一种无容量的阻塞队列,要求 put() 和 take() 操作严格配对阻塞,实现生产者与消费者间的点对点、无缓冲同步通信。

SynchronousQueue 是 Java 并发包中一种特殊的阻塞队列,它不存储元素,每个插入操作必须等待另一个线程的移除操作,反之亦然。这天然适合“生产者直连消费者”模型——即生产者不缓存数据,必须等消费者就绪后才交付,实现真正的点对点、无缓冲通信。
理解 SynchronousQueue 的核心特性
它内部没有容量(capacity = 0),put() 和 take() 总是成对阻塞配对:
- 调用 put(e) 的线程会一直阻塞,直到有另一个线程调用 take() 取走该元素;
- 调用 take() 的线程也会阻塞,直到有另一个线程调用 put() 放入元素;
- 不存在“队列满”或“队列空”的概念,只有“配对成功”或“等待配对”两种状态。
基础用法:一对一同步传递
最简场景下,一个生产者线程和一个消费者线程通过 SynchronousQueue 直接交接对象:
SynchronousQueue<string> queue = new SynchronousQueue();
// 生产者
new Thread(() -> {
try {
System.out.println("Producer: putting 'hello'");
queue.put("hello"); // 阻塞,直到消费者 take
System.out.println("Producer: delivered");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
// 消费者
new Thread(() -> {
try {
System.out.println("Consumer: waiting...");
String msg = queue.take(); // 阻塞,直到生产者 put
System.out.println("Consumer: received '" + msg + "'");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
</string>
输出顺序严格为:Producer: putting 'hello' → Consumer: waiting... → Consumer: received 'hello' → Producer: delivered,体现强同步性。
扩展为多对多直连(需配合线程池)
若希望多个生产者与多个消费者动态配对(如 RPC 请求响应、任务委派),可搭配固定大小的线程池使用:
- 创建 SynchronousQueue 实例,不传构造参数(默认公平模式,FIFO 配对);
- 用 Executors.newCachedThreadPool() 或自定义线程池启动生产者/消费者;
- 注意:SynchronousQueue 不保证“谁 put 就一定被谁 take”,而是按线程等待顺序配对(公平模式下)或抢占式(非公平,默认);
- 避免单个生产者长期阻塞——应设置超时(
offer(e, timeout, unit)/poll(timeout, unit))防止死锁。
关键注意事项
使用时需警惕几个易错点:
- 不能用于缓存:试图往里放多个元素会卡住,除非有对应数量的消费者同时等待;
- 不支持 peek()、isEmpty() 等查询方法:因为无内部存储,这些操作无意义;
- 中断敏感:put/take 被中断时抛 InterruptedException,务必正确处理;
- 慎用在高吞吐异步场景:因无缓冲,性能取决于双方线程调度及时性,不如 LinkedBlockingQueue 或 ArrayBlockingQueue 稳定。
它不是万能队列,而是为“即产即消”而生。用对场景时,能清晰表达协作契约,减少内存占用和延迟。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











