BlockingQueue和TransferQueue之间的区别

jvd*_*ste 49 java concurrency jsr166

关于BlockingQueue/LinkedBlockingQueue与jsr166y和java 7中的新TransferQueue/LinkedTransferQueue类型之间的区别,我有点困惑

Pet*_*aný 69

来自TransferQueue JavaDocs:

一个BlockingQueue,生产者可以等待消费者接收元素.TransferQueue可能在例如消息传递应用程序中很有用,其中生产者有时(使用方法转移(E))等待消费者调用take或poll接收元素,而在其他时候将元素排队(通过方法put)而不等待接收.

换句话说,当您使用BlockingQueue时,您只能将元素放入队列(如果队列已满,则阻止).使用TransferQueue,您也可以阻止,直到其他线程接收到您的元素(您必须使用新transfer方法).这是不同的.使用BlockingQueue,您不能等到其他线程删除您的元素(仅当您使用SynchronousQueue时,但这不是真正的队列).

除此之外,TransferQueue也是一个BlockingQueue.在TransferQueue中查看新的可用方法:http://download.oracle.com/javase/7/docs/api/java/util/concurrent/TransferQueue.html(transfer,tryTransfer,hasWaitingConsumer,getWaitingConsumerCount).


Java SE 7中的集合框架增强功能明确说明:

添加了接口TransferQueue.它是BlockingQueue接口的改进,生产者可以在其中等待消费者接收元素.此版本中还包含新接口的一个实现LinkedTransferQueue.


swi*_*her 7

简而言之,BlockingQueue 保证生产者制造的元素必须在队列中,而 TransferQueue 更进一步,它保证元素被某些消费者“消费”。


Eug*_*ene 5

很久以前的一个问题,@Peter 的回答非常详细。想要了解 TransferQueue 在实践中是如何工作的,或许可以参考下面的现场演示。

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();
    }

}
Run Code Online (Sandbox Code Playgroud)

输出是:

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
Run Code Online (Sandbox Code Playgroud)

transfer就是差异发生的地方。

将元素传输给消费者,必要时等待。

更准确地说,如果存在已经等待接收它的消费者(在采取或定时轮询中),则立即传输指定的元素,否则等待直到消费者收到该元素。

作为 javadoc,他们transfer会等到消费者拿走产品。

这就是为什么"Producer waiting to transfer: 0"首先被调用的原因,大约 2 秒后,在消费者收到后,Producer transfered: 0然后调用。