SynchronousQueue 的核心设计是“不存储元素”,所有插入操作必须等待对应移除操作,通过线程配对直接交接,无任何缓冲区,依赖 Transferer 协议实现公平或非公平模式下的零拷贝传递。

SynchronousQueue 的核心设计就是“不存储元素”,它不保留任何待处理的任务或数据,所有插入操作(put)必须等待另一个线程执行对应的移除操作(take),反之亦然。这种“手递手”式的直接交接,是通过线程协作与阻塞机制实现的,而非靠内部数组或链表缓冲。
依赖线程配对完成传递
它内部没有容量为 1 的缓冲区,也没有队列结构。每次 put(e) 调用不会把元素存起来,而是挂起当前线程,直到有另一个线程恰好调用 take();此时两个线程在同一个同步点“碰头”,元素直接从生产者线程交给消费者线程,不经过任何中间容器。
- 如果先调用
take(),该线程会阻塞,等待后续的put() - 如果先调用
put(e),该线程会阻塞,等待后续的take() - 两者必须成对出现,才能完成一次传递,不存在“暂存”环节
底层使用 Transferer 协作协议
JDK 中 SynchronousQueue 有两种实现模式(由构造参数决定):公平模式(TransferQueue)和非公平模式(TransferStack)。它们都基于一个统一的 Transferer 接口,核心方法是 transfer(e, timed, nanos):
- 传入元素(或
null表示 take 请求) - 尝试匹配已等待的对方线程(如 put 等 take,或 take 等 put)
- 匹配成功则直接交换数据并唤醒对方;失败则将当前线程加入等待队列并阻塞
无本地存储,全靠线程状态切换
它的内部不维护元素数组、链表、甚至单个变量来保存数据。所有“待传递”的信息都记录在线程自身的栈帧或等待节点中:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 每个等待线程的节点里只存自己的线程引用、请求类型(put/take)、数据(如果是 put)或结果槽(如果是 take)
- 元素值仅在两个线程的寄存器/局部变量间流动,不落内存缓冲区
- GC 友好:一旦传递完成,元素对象直接由接收方持有,发送方不再引用
典型使用场景印证“零存储”特性
比如配合 Executors.newCachedThreadPool(),任务提交到 SynchronousQueue 后不会排队等待空闲线程,而是:
- 若已有空闲线程在
take(),任务立刻交出并执行 - 若无空闲线程,则创建新线程,并让它立即执行该任务(即新线程自己完成
take()) - 绝不会出现“任务积压在队列里等很久”的情况
这种设计让 SynchronousQueue 成为真正意义上的“交换通道”,不是缓冲区,也不是队列,而是一个线程间同步的信号门——一进一出,严丝合缝。

















