java - Diferencia entre BlockingQueue y TransferQueue
concurrency jsr166 (4)
Aunque parece que hay alguna forma de diferencia de rendimiento; ver ArrayBlockingQueue vs LinkedTransferQueue y amigos
Estoy un poco confundido en cuanto a cuál es la diferencia entre BlockingQueue / LinkedBlockingQueue y los nuevos tipos TransferQueue / LinkedTransferQueue de jsr166y y java 7
Desde TransferQueue JavaDocs :
Un BlockingQueue en el que los productores pueden esperar a que los consumidores reciban los elementos. Un TransferQueue puede ser útil, por ejemplo, en aplicaciones de transmisión de mensajes en las que los productores a veces (utilizando la transferencia de método (E)) esperan recibir los elementos por parte de los consumidores que invocan tomar o sondear, mientras que otras veces los elementos se ponen en cola (mediante el método put) sin esperar la recepción.
En otras palabras, cuando usa BlockingQueue, solo puede poner el elemento en la cola (y bloquear si la cola está llena). Con TransferQueue, también puede bloquear hasta que otro hilo reciba su elemento (debe usar un nuevo método de transfer
para eso). Esta es la diferencia. Con BlockingQueue, no puede esperar hasta que otro hilo elimine su elemento (solo cuando utiliza SynchronousQueue, pero eso no es realmente una cola).
Aparte de esto, TransferQueue también es un BlockingQueue. Consulte los nuevos métodos disponibles en TransferQueue: http://download.oracle.com/javase/7/docs/api/java/util/concurrent/TransferQueue.html (transferencia, tryTransfer, hasWaitingConsumer, getWaitingConsumerCount).
Las mejoras del marco de colecciones en Java SE 7 dicen explícitamente:
La interfaz TransferQueue ha sido añadida. Es un refinamiento de la interfaz BlockingQueue en la que los productores pueden esperar a que los consumidores reciban los elementos. Una implementación de la nueva interfaz también se incluye en esta versión, LinkedTransferQueue.
En resumen, BlockingQueue garantiza que el elemento creado por el productor debe estar en la cola, mientras que TransferQueue va un paso más allá, garantiza que el elemento "consumido" por algún consumidor.
Una pregunta hace mucho tiempo y la respuesta de @ Peter es realmente elaborada. Para las personas que quieran saber cómo funciona TransferQueue en la práctica, tal vez pueda consultar la demostración en vivo a continuación.
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();
}
}
La salida es:
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
La transfer
es donde ocurre la diferencia.
Transfiere el elemento a un consumidor, esperando si es necesario para hacerlo.
Más precisamente, transfiere el elemento especificado inmediatamente si existe un consumidor que ya está esperando para recibirlo (en una encuesta o en una encuesta programada), de lo contrario, espera hasta que el consumidor reciba el elemento.
Como javadoc, la transfer
esperará hasta que el consumidor haya retirado el producto.
Esa es la razón por la que "Producer waiting to transfer: 0"
se llama primero y después de unos 2 segundos, después de que el consumidor lo haya recibido, se Producer transfered: 0
el Producer transfered: 0
.