【问题标题】:Difference between BlockingQueue and TransferQueueBlockingQueue 和 TransferQueue 的区别
【发布时间】:2011-11-11 04:01:01
【问题描述】:

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

【问题讨论】:

    标签: java concurrency jsr166


    【解决方案1】:

    来自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 (transfer, tryTransfer, hasWaitingConsumer, getWaitingConsumerCount)。


    Collections Framework Enhancements in Java SE 7 明确表示:

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

    【讨论】:

    • 我觉得我浏览文档的速度有点太快了,因为界面非常相似。谢谢你的解释。
    • 解释的很好,特别是增强部分说TransferQueue不过是BlockingQueue+receipt功能。
    • 另一个特点是生产者可以使用tryTransfer()提供元素只有如果有等待消费者。
    【解决方案2】:

    虽然看起来确实存在某种形式的性能差异;见ArrayBlockingQueue vs LinkedTransferQueue and friends

    【讨论】:

    • 链接无效
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      很久以前的一个问题,@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 是不同之处。

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

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

      作为 javadoc,transfer 将等到消费者拿走产品。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-06-29
        • 1970-01-01
        • 1970-01-01
        • 2023-04-01
        • 2013-09-29
        • 2018-08-22
        • 2013-08-07
        • 2011-10-20
        相关资源
        最近更新 更多