TransferQueue represents a transfer queue.
In a TransferQueue, a producer will wait to hand off an element to a consumer.
This is a useful for a message passing application, where a producer makes sure that its message has been consumed by a consumer.
A producer hands off an element to a consumer using the transfer(E element) method of the TransferQueue.
When a producer invokes this method, it waits until a consumer takes its element.
If the TransferQueue has more than one element, all its elements must be consumed.
The tryTransfer() method provides a non-blocking and a timeout version of the method.
TransferQueue getWaitingConsumerCount() method returns the number of waiting consumers.
hasWaitingConsumer() method returns true if there is a waiting consumer; otherwise, it returns false.
LinkedTransferQueue is an implementation class for the TransferQueue interface.
The following code creates DataProducer class whose instance represents a producer for a TransferQueue.
import java.util.Random; import java.util.concurrent.LinkedTransferQueue; import java.util.concurrent.TransferQueue; import java.util.concurrent.atomic.AtomicInteger; class DataProducer extends Thread { private final String name; private final TransferQueue<Integer> tQueue; private final AtomicInteger sequence; public DataProducer(String name, TransferQueue<Integer> tQueue, AtomicInteger sequence) {// w w w . j a v a 2s. c o m this.name = name; this.tQueue = tQueue; this.sequence = sequence; } @Override public void run() { while (true) { try { int sleepTime = 3; Thread.sleep(sleepTime * 1000); int nextNum = this.sequence.incrementAndGet(); if (nextNum % 2 == 0) { System.out.format("%s: Enqueuing: %d%n", name, nextNum); tQueue.put(nextNum); // Enqueue } else { System.out.format("%s: Handing off: %d%n", name, nextNum); System.out.format("%s: has a waiting consumer: %b%n", name, tQueue.hasWaitingConsumer()); tQueue.transfer(nextNum); // A hand off } } catch (InterruptedException e) { e.printStackTrace(); } } } } class TQConsumer extends Thread { private final String name; private final TransferQueue<Integer> tQueue; private final Random rand = new Random(); public TQConsumer(String name, TransferQueue<Integer> tQueue) { this.name = name; this.tQueue = tQueue; } @Override public void run() { while (true) { try { // Sleep for 1 to 5 random number of seconds int sleepTime = rand.nextInt(5) + 1; Thread.sleep(sleepTime * 1000); int item = tQueue.take(); System.out.format("%s removed: %d%n", name, item); } catch (InterruptedException e) { e.printStackTrace(); } } } } public class Main { public static void main(String[] args) { final TransferQueue<Integer> tQueue = new LinkedTransferQueue<>(); final AtomicInteger sequence = new AtomicInteger(); // Initialize transfer queue with five items for (int i = 0; i < 5; i++) { try { tQueue.put(sequence.incrementAndGet()); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("Initial queue: " + tQueue); // Create and start a producer and a consumer new DataProducer("Producer-1", tQueue, sequence).start(); new TQConsumer("Consumer-1", tQueue).start(); } }