Difference between BlockingQueue and TransferQueue

19,590

Solution 1

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

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

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.

Share:
19,590
jvdneste
Author by

jvdneste

Updated on June 06, 2022

Comments

  • jvdneste
    jvdneste almost 2 years

    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