Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Java SynchronousQueue: a handoff has no storage capacity

Last updated: 5 Oct 20264 min read
tutorial
IntermediateBy AITrove Editorial

SynchronousQueue transfers an element directly between a producer and a waiting consumer; it does not retain elements in an internal queue.

Observe the zero-capacity contract

An immediate offer fails when no consumer is ready. A subsequent put waits until a consumer accepts the value. The fixture starts the consumer only after the failed offer, then joins it before printing the received shipment ID.

This handoff can apply backpressure, but a stalled consumer can hold the producer indefinitely. Use a timed offer or cancellation where the caller has a deadline. Buffered blocking queues decouple arrival and consumption up to their configured capacity.

Separate transfer from processing

A successful put means the consumer accepted the element; it does not prove that the consumer completed its business work. If acknowledgment matters, pair the transfer with a separate completion signal or durable result record.

Working program

Java
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.atomic.AtomicReference;

public class ShipmentDirectHandoff {
    public static void main(String[] args) throws InterruptedException {
        SynchronousQueue<String> handoff = new SynchronousQueue<>();
        System.out.println("immediate=" + handoff.offer("lot-47"));
        AtomicReference<String> received = new AtomicReference<>();
        Thread receiver = new Thread(() -> {
            try { received.set(handoff.take()); }
            catch (InterruptedException stopped) { Thread.currentThread().interrupt(); }
        });
        receiver.start();
        handoff.put("lot-82");
        receiver.join();
        System.out.println("received=" + received.get());
    }
}

Output

Output
immediate=false
received=lot-82

Cost and ownership

The queue itself has no element capacity, although producer and consumer tasks still occupy threads or other runtime resources. Transfer can block; its latency is governed by consumer readiness, not a queue traversal cost.

Common Mistakes

  • Do not assume offer stores work when no consumer exists.
  • Do not treat a completed put as proof that processing completed.
  • Do not use unbounded waits when the request has a deadline.

Read next

Java blocking queues: bounded capacity and backpressure, Java BlockingQueue drainTo: batch size is not a transaction, Java cancellation: timed waits and cooperative interruption, Java ConcurrentLinkedQueue: size is not an admission limit.

Continue with: Java Exchanger: swap buffers at a two-party rendezvous, Java LinkedTransferQueue: wait until a consumer receives work.

java
concurrency
synchronousqueue-handoff
Storage details