Difference between BlockingQueue and TransferQueue

JavaConcurrencyJsr166

Java Problem Overview


I am a little bit confused as to what the difference is between BlockingQueue/LinkedBlockingQueue and the new TransferQueue/LinkedTransferQueue types from jsr166y and java 7

Java Solutions


Solution 1 - Java

From TransferQueue JavaDocs:

> A BlockingQueue in which producers may wait for consumers to receive elements. A TransferQueue may be useful for example in message passing applications in which producers sometimes (using method transfer(E)) await receipt of elements by consumers invoking take or poll, while at other times enqueue elements (via method put) without waiting for receipt.

In other words, when you use BlockingQueue, you can only put element into queue (and block if queue is full). With TransferQueue, you can also block until other thread receives your element (you must use new transfer method for that). This is the difference. With BlockingQueue, you cannot wait until other thread removes your element (only when you use SynchronousQueue, but that isn't really a queue).

Other than this, TransferQueue is also a BlockingQueue. Check out new available methods in TransferQueue: http://download.oracle.com/javase/7/docs/api/java/util/concurrent/TransferQueue.html (transfer, tryTransfer, hasWaitingConsumer, getWaitingConsumerCount).


Collections Framework Enhancements in Java SE 7 says explicitly:

> The interface TransferQueue has been added. It is a refinement of the BlockingQueue interface in which producers can wait for consumers to receive elements. One implementation of the new interface is also included in this release, LinkedTransferQueue.

Solution 2 - Java

In short, BlockingQueue guarantees that the element made by producer must be in the queue, while TransferQueue gets one step further, it guarantees that the element "consumed" by some consumer.

Solution 3 - Java

A question long time ago and @Peter's answer is really elaborate. For people who wants to know how TransferQueue works in practice, maybe you can refer to the live demo below.

import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.TransferQueue;

public class TransferQueueExample {

	TransferQueue<String> queue = new LinkedTransferQueue<String>();

	class Producer implements Runnable{

		@Override
		public void run() {
			// TODO Auto-generated method stub
			for(int i = 0; i < 2; i++){
				try{
					System.out.println("Producer waiting to transfer: " + i);
					queue.transfer("" + i);
					System.out.println("Producer transfered: " + i);
				}catch(Exception e){
					e.printStackTrace();
				}
			}
		}
		
	}
	
	class Consumer implements Runnable{

		@Override
		public void run() {
			// TODO Auto-generated method stub
			for(int i = 0; i < 2; i++){
				try{
					Thread.sleep(2000);
					System.out.println("Consumer waiting to comsume: " + i);
					queue.take();
					System.out.println("Consumer consumed: " + i);
				}catch(Exception e){
					e.printStackTrace();
				}
			}
		}
	}
	
	public static void main(String args[]){
		TransferQueueExample example = new TransferQueueExample();
		new Thread(example.new Producer()).start();
		new Thread(example.new Consumer()).start();
	}
	
}

The output is:

Producer waiting to transfer: 0
Consumer waiting to comsume: 0
Consumer consumed: 0
Producer transfered: 0
Producer waiting to transfer: 1
Consumer waiting to comsume: 1
Consumer consumed: 1
Producer transfered: 1

The transfer is where the difference happens.

> Transfers the element to a consumer, waiting if necessary to do so. > > More precisely, transfers the specified element immediately if there > exists a consumer already waiting to receive it (in take or timed > poll), else waits until the element is received by a consumer.

As the javadoc, the transfer will wait until the consumer has taken the product away.

That's the reason why "Producer waiting to transfer: 0" is called firstly and after about 2 seconds, after it has been received by the consumer, the Producer transfered: 0 is called then.

Solution 4 - Java

Although there does seem to be some form of performance difference; see ArrayBlockingQueue vs LinkedTransferQueue and friends

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjvdnesteView Question on Stackoverflow
Solution 1 - JavaPeter ŠtibranýView Answer on Stackoverflow
Solution 2 - JavaswimmingfisherView Answer on Stackoverflow
Solution 3 - JavaEugeneView Answer on Stackoverflow
Solution 4 - JavaEgworView Answer on Stackoverflow