linkedtransferqueue 的 transfer 方法实现生产者与消费者间的同步传递:线程阻塞直至元素被 take() 等操作主动取走,不保证入队;其无锁设计基于 cas 与 park/unpark 实现直接交接;区别于 trytransfer(尝试匹配不阻塞)和 offer(无条件入队)。

LinkedTransferQueue 的 transfer 方法不是简单地把元素放进队列,而是“等待消费者真正接收”——它会阻塞当前线程,直到有另一个线程调用 take()、poll()(带超时或不带超时)、tryTransfer()(成功时)等**主动取走该元素**的操作,才算完成。
transfer 的核心语义:同步传递,而非入队
与 put() 或 offer() 不同,transfer(E e) 不保证元素最终留在队列中。它的设计目标是实现生产者和消费者之间的**直接交接(hand-off)**:
- 如果有空闲消费者正在
take()或阻塞等待,生产者线程会立即把元素交给它,不经过队列缓冲; - 如果没有消费者在等待,生产者线程就会阻塞,挂起自己,直到有消费者来取;
- 一旦交接完成(无论是否经过队列中转),
transfer()才返回,表示“已送达”。
底层如何实现等待与唤醒
LinkedTransferQueue 是无锁(lock-free)队列,基于 CAS 和自旋 + 线程停放(LockSupport.park())机制:
- 当调用
transfer()时,线程先尝试匹配等待中的消费者节点(例如一个处于take()阻塞状态的节点); - 若匹配成功,直接交换数据并唤醒消费者线程,自身返回;
- 若无匹配者,当前线程会构造一个“数据节点”(mode = DATA),插入队列尾部,并进入阻塞状态(
park()); - 后续消费者调用
take()时,会扫描队列,找到这个未匹配的数据节点,完成交接并唤醒对应生产者。
和 tryTransfer、offer 的关键区别
三者行为差异直接影响线程协作模型:
-
transfer(e):必须等到有人拿走才返回,适合强同步场景(如任务委派、请求-响应配对); -
tryTransfer(e):仅尝试匹配,有等待消费者就立刻交出,否则直接返回false,不阻塞; -
offer(e):无条件入队,不管有没有消费者,也不等待,典型异步缓冲行为。
实际使用注意事项
因 transfer() 可能无限期阻塞,需谨慎用于不可控环境:
- 避免在没有配套消费者逻辑的场景下调用,否则线程可能永久挂起;
- 不适用于“尽力而为”的投递(此时应选
offer()或带超时的tryTransfer(e, timeout, unit)); - 调试时注意:线程堆栈中若看到
TransferQueue.transfer+Unsafe.park,基本说明它正卡在等消费者; - 它和
SynchronousQueue的put()行为相似,但 LinkedTransferQueue 支持同时支持“可选缓冲”(其他方法)和“强制同步”两种模式。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











