synchronousqueue 是无缓冲阻塞队列,put() 与 take() 必须配对阻塞等待,实现线程间直接数据交接;默认非公平,可选公平模式;常用于生产者-消费者一一配对或 threadpoolexecutor 弹性线程池。

SynchronousQueue 是 Java 并发包中一种特殊的阻塞队列,它不存储元素——每个插入操作必须等待另一个线程的移除操作,反之亦然。这种“手递手”式的直接交接,天然适合实现无缓冲的线程协作,比如生产者-消费者模型中要求严格一一配对的场景。
理解 SynchronousQueue 的核心行为
它内部没有容量(哪怕 1),put() 和 take() 操作总是成对阻塞等待:一个线程调用 put() 后会挂起,直到另一个线程调用 take();反之亦然。这不同于 ArrayBlockingQueue 或 LinkedBlockingQueue,后者允许暂存数据。
注意:SynchronousQueue 默认使用非公平策略(Fairness = false),即不保证等待时间最长的线程优先被唤醒,若需 FIFO 行为,可显式传入 new SynchronousQueue(true) 构造公平队列。
典型用法:生产者-消费者直接交接
以下是一个最小可行示例,展示两个线程如何通过 SynchronousQueue 实现零延迟、零缓冲的数据传递:
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class SyncQueueExample {
private static final SynchronousQueue<string> queue = new SynchronousQueue();
public static void main(String[] args) throws InterruptedException {
// 启动消费者线程(先启动,避免生产者过早阻塞)
Thread consumer = new Thread(() -> {
try {
String msg = queue.take(); // 阻塞等待
System.out.println("消费: " + msg);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
consumer.start();
// 生产者线程(稍后执行)
Thread.sleep(100); // 确保 consumer 已进入 take()
Thread producer = new Thread(() -> {
try {
queue.put("Hello from producer"); // 阻塞直到被 take()
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
producer.start();
producer.join();
consumer.join();
}
}</string>
运行结果稳定输出 消费: Hello from producer,说明数据未经过任何中间缓存,而是由生产者线程直接“交到”消费者线程手中。
配合线程池使用的常见模式
SynchronousQueue 常作为 ThreadPoolExecutor 的工作队列,尤其适用于“来一个任务、立即分配一个线程执行”的场景(如 Web 请求处理):
- 当核心线程都在忙时,新任务不会排队等待,而是直接触发创建新线程(只要未达 maximumPoolSize)
- 一旦线程空闲超时(keepAliveTime),就会被回收,保持资源精简
- 这种组合天然支持弹性伸缩,且无任务堆积风险
示例:
ExecutorService executor = new ThreadPoolExecutor(
2, // corePoolSize
4, // maxPoolSize
30L, // keepAliveTime
TimeUnit.SECONDS,
new SynchronousQueue
<h3>注意事项与适用边界</h3>
<p>SynchronousQueue 不适合需要解耦或削峰填谷的场景。如果生产者和消费者节奏严重不匹配(例如生产者爆发式提交、消费者处理缓慢),会导致大量线程阻塞在 put() 上,可能引发 OOM 或响应停滞。</p>
- 务必确保配对操作存在:有 put 就得有 take,否则线程永久阻塞
- 慎用于高吞吐但低配对率的系统;更适合强协作、低延迟、一对一语义明确的模块间通信
- 可配合
offer(E, timeout, unit)和poll(timeout, unit)实现带超时的非阻塞尝试,提升健壮性
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











