Разница между BlockingQueue и TransferQueue
Я немного сбит с толку относительно различия между BlockingQueue/LinkedBlockingQueue и новыми типами TransferQueue/LinkedTransferQueue из jsr166y и java 7
4 ответа
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.
Короче говоря, BlockingQueue гарантирует, что элемент, созданный производителем, должен находиться в очереди, в то время как TransferQueue продвигается на один шаг дальше, он гарантирует, что элемент "потребляется" каким-либо потребителем.
Вопрос давным-давно и ответ @ Петра действительно сложный. Для людей, которые хотят знать, как 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
называется тогда.
Хотя, похоже, существует некоторая разница в производительности; увидеть ArrayBlockingQueue против LinkedTransferQueue и друзей