Разница между BlockingQueue и TransferQueue - PullRequest
47 голосов
/ 06 сентября 2011

Я немного сбит с толку относительно разницы между BlockingQueue / LinkedBlockingQueue и новыми типами TransferQueue / LinkedTransferQueue из jsr166y и java 7

Ответы [ 4 ]

66 голосов
/ 06 сентября 2011

С 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).


Усовершенствования Framework коллекций в Java SE 7 прямо говорит:

Добавлен интерфейс TransferQueue. Это усовершенствование интерфейса BlockingQueue, в котором производители могут ждать, пока потребители получат элементы. Одна реализация нового интерфейса также включена в этот выпуск, LinkedTransferQueue.

2 голосов
/ 10 февраля 2014

Короче говоря, BlockingQueue гарантирует, что элемент, созданный производителем, должен находиться в очереди, в то время как TransferQueue продвигается на один шаг вперед, это гарантирует, что элемент "потребляется" каким-то потребителем.

1 голос
/ 20 ноября 2017

Вопрос давным-давно и @ Петр ответ действительно сложный.Для людей, которые хотят знать, как 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разница случается.

Передает элемент потребителю, ожидая, если это необходимо,

Точнее, передает указанный элемент немедленно, если существует потребитель, уже ожидающий его полученияили синхронизированный опрос), иначе ожидает, пока элемент не будет получен потребителем.

Как и Javadoc, transfer будет ждать, пока потребитель не заберет продукт.

По этой причине сначала вызывается "Producer waiting to transfer: 0", а через 2 секунды после его получения потребителем вызывается Producer transfered: 0.

0 голосов
/ 04 ноября 2013

Хотя, похоже, существует некоторая разница в производительности; см. ArrayBlockingQueue против LinkedTransferQueue и друзей

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...