Je suis un peu confus quant à la différence entre BlockingQueue/LinkedBlockingQueue et les nouveaux types TransferQueue/LinkedTransferQueue de jsr166y et Java 7.
Une file d'attente Blocking dans laquelle les producteurs peuvent attendre que les consommateurs reçoivent des éléments. Une TransferQueue peut être utile, par exemple, dans les applications de transmission de messages dans lesquelles les producteurs attendent parfois (à l'aide de la méthode de transfert (E)) de recevoir des éléments invoquant une prise ou une interrogation, alors que d'autres mettent en file d'attente des éléments (via une méthode mise) sans attendre la réception.
En d'autres termes, lorsque vous utilisez BlockingQueue, vous pouvez uniquement mettre un élément en file d'attente (et le bloquer si la file d'attente est pleine). Avec TransferQueue, vous pouvez également bloquer jusqu'à ce qu'un autre thread reçoive votre élément (vous devez utiliser la nouvelle méthode transfer
pour cela). C'est la différence Avec BlockingQueue, vous ne pouvez pas attendre qu'un autre thread supprime votre élément (uniquement lorsque vous utilisez SynchronousQueue, mais ce n'est pas vraiment une file d'attente).
Autre que cela, TransferQueue est également une BlockingQueue. Découvrez les nouvelles méthodes disponibles dans TransferQueue: http://download.Oracle.com/javase/7/docs/api/Java/util/concurrent/TransferQueue.html (transfer, tryTransfer, hasWaitingConsumer, getWaitingConsumerCount).
Améliorations apportées à la structure de collections dans Java SE 7 dit explicitement:
L'interface TransferQueue a été ajoutée. Il s'agit d'un raffinement de l'interface BlockingQueue dans lequel les producteurs peuvent attendre que les consommateurs reçoivent des éléments. Une version de la nouvelle interface, LinkedTransferQueue, est également incluse dans cette version.
En bref, BlockingQueue garantit que l’élément fabriqué par le producteur doit se trouver dans la file d’attente, tandis que TransferQueue franchit une étape supplémentaire, il garantit que l’élément "consommé" par certains consommateurs.
Une question posée il y a longtemps et la réponse de @ Peter est vraiment complexe. Pour ceux qui veulent savoir comment TransferQueue fonctionne dans la pratique, vous pouvez peut-être consulter la démonstration en direct ci-dessous.
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 sortie est:
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
est l'endroit où la différence se produit.
Transfère l'élément à un consommateur, en attendant si nécessaire.
Plus précisément, transfère immédiatement l’élément spécifié s’il existe Il existe un consommateur qui attend déjà de le recevoir (dans le sondage take ou timed ), sinon attend que l'élément soit reçu par un consommateur.
En tant que javadoc, la transfer
attendra que le consommateur ait retiré le produit.
C’est la raison pour laquelle "Producer waiting to transfer: 0"
est appelé en premier et au bout de 2 secondes environ, après avoir été reçu par le consommateur, le Producer transfered: 0
est ensuite appelé.
Bien qu'il semble y avoir une certaine forme de différence de performance; voir ArrayBlockingQueue vs LinkedTransferQueue et ses amis