LinkedTransferQueue
LinkedTransferQueue is arguably the most advanced BlockingQueue in the JDK. It implements the TransferQueue interface, which provides a middle ground between LinkedBlockingQueue and SynchronousQueue.
Source Code #
The “Dual Queue” Algorithm #
LinkedTransferQueue uses a “dual queue” algorithm (Scherer & Scott). A dual queue is a single linked structure that can hold either data nodes (provided by producers) or request nodes (provided by consumers).
public interface TransferQueue<E> extends BlockingQueue<E> {
// Transfers the element to a consumer, blocking if necessary
void transfer(E e) throws InterruptedException;
// Tries to transfer immediately, returns false if no consumer waiting
boolean tryTransfer(E e);
// Tries to transfer, blocks for a specific time if needed
boolean tryTransfer(E e, long timeout, TimeUnit unit) throws InterruptedException;
// Returns true if there is at least one waiting consumer
boolean hasWaitingConsumer();
}
Unlike LinkedBlockingQueue, which uses ReentrantLock, LinkedTransferQueue is designed to be mostly wait-free using CAS (Compare-And-Swap) operations for better scalability on modern multi-core processors.
Canonical Usage #
When to use: Use LinkedTransferQueue when you need a high-throughput, unbounded queue that can optionally act as a direct handoff (transfer()). It is a general-purpose replacement for LinkedBlockingQueue in performance-critical applications.
Common Patterns:
- Hybrid Producer-Consumer: Use
put()for standard asynchronous queuing andtransfer()when you need to be sure a consumer has actually started processing the item before the producer continues. - Direct Request Fulfillment: It can fulfill a consumer’s request immediately if a producer is already waiting, or vice versa.
// Unbounded high-performance queue
TransferQueue<String> queue = new LinkedTransferQueue<>();
// Traditional put (producer proceeds immediately)
queue.put("Asynchronous Task");
// Transfer (producer blocks until a consumer takes it)
queue.transfer("Critical Synchronous Task");
Performance Trade-offs #
- Pros: Scales exceptionally well with thread count. Combines the best of
LinkedBlockingQueueandSynchronousQueue. Minimal locking. - Cons: Every insertion allocates a
Node. Unbounded, so it must be used carefully to avoidOutOfMemoryError.