Подтвердить что ты не робот

Разница между BlockingQueue и TransferQueue

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

4b9b3361

Ответ 1

От TransferQueue JavaDocs:

A BlockingQueue, в котором производители могут ждать, пока потребители получат элементы. TransferQueue может быть полезен, например, в приложениях для передачи сообщений, в которых производители иногда (с использованием передачи метода (E)) ждут получения элементов потребителями, которые вызывают прием или опрос, а в других случаях - элементы очереди (через метод 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.

Ответ 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 происходит различие.

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

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

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

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