BlockingQueue 和 TransferQueue 的区别

发布于 2024-12-03 01:09:24 字数 112 浏览 8 评论 0原文

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

掌心的温暖 2024-12-10 01:09:24

来自 TransferQueue JavaDocs

一个BlockingQueue,生产者可以在其中等待消费者接收元素。 TransferQueue 在消息传递应用程序中可能很有用,其中生产者有时(使用方法 transfer(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(传输、tryTransfer、hasWaitingConsumer、getWaitingConsumerCount)。


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

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

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.

赏烟花じ飞满天 2024-12-10 01:09:24

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

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.

╰◇生如夏花灿烂 2024-12-10 01:09:24

很久以前的一个问题,@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();
    }

}

输出是:

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

transfer 是差异发生的地方。

将元素传输给使用者,并在必要时等待。

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

与 javadoc 一样,传输 将等到消费者拿走产品为止。

这就是为什么首先调用 "Producer waiting to transfer: 0" ,大约 2 秒后,消费者收到后, Producer Transfered: 0 是然后打电话。

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.

随梦而飞# 2024-12-10 01:09:24

尽管似乎确实存在某种形式的性能差异;请参阅 ArrayBlockingQueue 与 LinkedTransferQueue 和朋友

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文