62 votes

Différence entre BlockingQueue et TransferQueue

Je suis un peu confus quant à la différence entre BlockingQueue/LinkedBlockingQueue et les nouveaux types TransferQueue/LinkedTransferQueue de jsr166y et de java 7.

83voto

Peter Štibraný Points 17507

Desde TransferQueue JavaDocs :

Une BlockingQueue 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 passage de messages dans lesquelles les producteurs attendent parfois (à l'aide de la méthode transfer(E)) la réception d'éléments par des consommateurs invoquant take ou poll, tandis qu'à d'autres moments, ils mettent des éléments en file d'attente (à l'aide de la méthode put) sans attendre la réception.

En d'autres termes, lorsque vous utilisez BlockingQueue, vous pouvez uniquement placer un élément dans la file d'attente (et bloquer si la file d'attente est pleine). Avec TransferQueue, vous pouvez également bloquer jusqu'à ce que l'autre thread reçoive votre élément (vous devez utiliser new transfer pour cela). C'est là toute la différence. Avec BlockingQueue, vous ne pouvez pas attendre que l'autre thread retire votre élément (uniquement lorsque vous utilisez SynchronousQueue, mais ce n'est pas vraiment une file d'attente).

En outre, 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 du cadre des 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 laquelle les producteurs peuvent attendre que les consommateurs reçoivent des éléments. Une implémentation de la nouvelle interface est également incluse dans cette version, LinkedTransferQueue.

0 votes

Je pense que j'ai parcouru la documentation un peu trop rapidement car les interfaces étaient très similaires. Merci pour l'explication.

1 votes

Expliqué très bien, surtout la partie amélioration qui dit que TransferQueue n'est rien d'autre que la fonctionnalité BlockingQueue+receipt.

0 votes

Une autre caractéristique est qu'un producteur peut utiliser tryTransfer() offrir un élément seulement s'il y a un consommateur en attente.

9voto

swimmingfisher Points 501

En bref, BlockingQueue garantit que l'élément fabriqué par le producteur doit se trouver dans la file d'attente, tandis que TransferQueue va un peu plus loin, il garantit que l'élément est "consommé" par un certain consommateur.

5voto

upma Points 517

Une question posée il y a longtemps et la réponse de @Peter est très élaborée. Pour les personnes qui veulent savoir comment TransferQueue fonctionne en pratique, vous pouvez peut-être vous référer à la démo live 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

El transfer c'est là que la différence se produit.

Transfère l'élément à un consommateur, en attendant si nécessaire de le faire.

Plus précisément, transfère l'élément spécifié immédiatement s'il y a s'il existe un consommateur qui attend déjà de le recevoir (en take ou timed poll), sinon il attend que l'élément soit reçu par un consommateur.

Comme la javadoc, le transfer attendra que le consommateur ait emporté le produit.

C'est la raison pour laquelle "Producer waiting to transfer: 0" est appelé en premier lieu et après environ 2 secondes, après qu'il ait été reçu par le consommateur, la Producer transfered: 0 est alors appelé.

-2voto

Egwor Points 944

Bien qu'il semble y avoir une certaine forme de différence de performance ; voir ArrayBlockingQueue vs LinkedTransferQueue et amis

0 votes

Le lien n'est pas valide

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X