核心区别在于“是否缓存任务”:SynchronousQueue不保存任务,需生产者与消费者直接交接;LinkedBlockingQueue则暂存任务形成缓冲区。前者容量为0、无存储、强制同步阻塞;后者基于链表、支持有界/无界、异步存取、双锁并行。适用场景不同:前者适合低延迟、线程充裕场景(如CachedThreadPool),后者适合需背压控制、容忍积压的场景。

核心区别在于“是否缓存任务”:SynchronousQueue不保存任何任务,必须生产者和消费者直接交接;LinkedBlockingQueue则会暂存任务,形成缓冲区。
存储机制完全不同
LinkedBlockingQueue 是一个真实存在的队列,内部用链表维护元素,支持 FIFO 顺序。它可以是有界(如 new LinkedBlockingQueue(100))或无界(默认容量为 Integer.MAX_VALUE),任务来了就入队,等线程空闲时再取出执行。
SynchronousQueue 逻辑上容量为 0,没有存储空间。每次 put() 必须等待另一个线程同时调用 take(),反之亦然。它更像一个“手递手”的通道,不是容器。
线程协作方式差异明显
LinkedBlockingQueue 允许生产者和消费者异步运行。生产者把任务放进去就能返回(除非队列已满),消费者从队列取任务也不依赖当前是否有生产者在操作。它用两把独立锁(putLock 和 takeLock)实现入队/出队并行,吞吐较稳。
SynchronousQueue 强制同步交接。没有消费者等着,put() 就一直阻塞;没有生产者提供数据,take() 也一直等。它的性能优势来自省去了队列维护开销,但要求配套线程池能快速响应——比如 Executors.newCachedThreadPool() 就依赖它按需创建线程。
适用场景截然不同
- 选 LinkedBlockingQueue:需要控制任务积压、防止 OOM、允许一定延迟处理。例如 Web 请求进线程池后排队等待,系统可设最大队列长度做背压。
- 选 SynchronousQueue:强调低延迟、任务不过夜、希望线程“来了就干”。适合突发流量小、处理快、线程资源较充裕的场景。注意:若 maximumPoolSize 设得太小,容易触发拒绝策略。
其他关键细节
LinkedBlockingQueue 的迭代器是 fail-fast 的,遍历时修改会抛异常;SynchronousQueue 的 iterator() 永远返回空,peek() 永远返回 null,isEmpty() 永远返回 true——这些都印证它“不存东西”的本质。
公平性方面:SynchronousQueue 可选公平(FIFO 等待)或非公平(LIFO,可能造成部分任务长期等待);LinkedBlockingQueue 默认无公平参数,其 FIFO 行为由链表结构自然保证。










