JavaRush /Blog Java /Random-FR /Exemple SynchronousQueue en Java - résoudre le problème P...
profeg
Niveau 18

Exemple SynchronousQueue en Java - résoudre le problème Producteur Consommateur

Publié dans le groupe Random-FR
Exemple SynchronousQueue en Java - résoudre le problème Producteur Consommateur
SynchronousQueue est un type spécial de BlockingQueue dans lequel chaque opération d'insertion doit attendre une commande de suppression correspondante dans un autre thread, et vice versa. Lorsque vous appelez la méthode put() sur une SynchronousQueue, elle se bloque jusqu'à ce qu'un autre thread en récupère cet élément. Par conséquent, si un autre thread tente d'en supprimer un élément et que l'élément n'est pas là, alors ce thread se bloque jusqu'à ce que l'autre thread mette l'élément dans la file d'attente. Vous pouvez considérer SynchronousQueue comme un athlète ( thread ) courant avec la torche olympique, il court avec la torche (l'objet qui est transmis) et la passe à un autre athlète qui attend de l'autre côté. Si vous faites attention au nom, vous comprendrez que SynchronousQueue est nommé ainsi pour une raison : il transfère les données de manière synchrone vers un autre thread ; il attend que quelqu'un récupère les données au lieu de simplement les insérer et les quitter (une opération asynchrone). Si vous connaissez CSP et Ada, vous savez que les files d'attente synchronisées sont similaires à la réunion de threads. Ils conviennent bien aux constructions de transfert de contrôle dans lesquelles un objet exécuté dans un thread doit se synchroniser avec un objet dans un autre thread afin de lui transmettre des informations, un événement ou une tâche. Dans les précédents didacticiels de programmation multithread, nous avons appris à résoudre le problème producteur-consommateur à l'aide des méthodes wait and notify et BlockingQueue . Nous allons maintenant apprendre comment appliquer le modèle producteur-consommateur à l'aide de SynchronousQueue. Cette classe prend en outre en charge un comportement équitable pour ordonner les attentes des threads producteur et consommateur. Par défaut, cet ordre n'est pas garanti. Cependant, les files d'attente créées avec des propriétés équitables garantissent l'accès aux threads dans une file d'attente FIFO (Firs In First Out).
Producteur/Consommateur utilisant SynchronousQueue en Java.
Exemple SynchronousQueue en Java - résoudre le problème Producer Consumer - 1 Comme je l'ai dit plus haut, il n'y a rien de mieux que le problème producteur-consommateur pour comprendre la communication inter-thread dans n'importe quel langage de programmation. Dans ce problème, un thread agit en tant que producteur qui produit des événements et des tâches, et l'autre thread agit en tant que consommateur. Un tampon partagé est utilisé pour transférer les données du producteur au consommateur. La difficulté de résoudre ce problème survient dans des cas extrêmes, par exemple lorsque le constructeur est obligé d'attendre parce que... le tampon est plein ou le consommateur est obligé d'attendre car le tampon est vide. Cela a été facilement résolu, car... La file d'attente de blocage fournissait non seulement un tampon pour stocker les données, mais également un contrôle de flux, bloquant le thread appelant la méthode put() (Producer) si le tampon était plein, et bloquant le thread appelant la méthode take() (Consumer) si le le tampon était vide. Nous allons maintenant résoudre ce même problème en utilisant SynchronousQueue, un type spécial de collections parallèles avec une capacité nulle. Dans l'exemple suivant, nous avons deux threads appelés PRODUCER et CONSUMER (donnez toujours des noms aux threads, c'est un très bon style de programmation multi-thread). Le premier thread publie le score dans le jeu, et le deuxième le consomme. Le score dans le jeu n'est rien de plus qu'un objet de type String. Mais si vous exécutez le programme avec un type différent, vous ne remarquerez aucune différence. Pour comprendre le fonctionnement de SynchronousQueue et comment résoudre le problème producteur-consommateur, vous devez : soit exécuter le programme de débogage (debug) dans l'environnement Eclipse , soit simplement démarrer le thread producteur en commentant consumer.start(); si le thread consommateur n'est pas en cours d'exécution, le thread producteur sera bloqué à queue.put(event); s'il est en cours d'exécution, vous ne pourrez pas voir le producteur [PRODUCER] publier l'événement :FOUR. Cela arrive parce que comportement spécifique de SynchronousQueue, qui garantit que le thread publiant les données se bloquera jusqu'à ce qu'un autre thread prenne les données, et vice versa. Vous pouvez tester le reste du code en commentant producteur.start(); et en démarrant uniquement le fil de discussion consommateur. Si vous étudiez attentivement ce que le programme génère, vous remarquerez que l’ordre de sortie est inversé. Il semble que le thread [CONSUMER] ait pris les données avant que le thread [PRODUCER] ne les produise. En effet, SynchronousQueue ne garantit pas la mise en file d'attente par défaut. Mais il a des règles d'équité qui définissent l'accès aux threads dans l'ordre FIFO. Vous pouvez activer ces règles en passant true au constructeur SynchronousQueue surchargé comme ceci : import java.util.concurrent.SynchronousQueue; /** * Java Program to solve Producer Consumer problem using SynchronousQueue. A * call to put() will block until there is a corresponding thread to take() that * element. * * @author Javin Paul */ public class SynchronousQueueDemo{ public static void main(String args[]) { final SynchronousQueue queue = new SynchronousQueue (); Thread producer = new Thread("PRODUCER") { public void run() { String event = "FOUR"; try { queue.put(event); // thread will block here System.out.printf("[%s] published event : %s %n", Thread .currentThread() .getName(), event); } catch (InterruptedException e) { e.printStackTrace(); } } }; producer.start(); // starting publisher thread Thread consumer = new Thread("CONSUMER") { public void run() { try { String event = queue.take(); // thread will block here System.out.printf("[%s] consumed event : %s %n", Thread .currentThread() .getName(), event); } catch (InterruptedException e) { e.printStackTrace(); } } }; consumer.start(); // starting consumer thread } } Output: [CONSUMER] consumed event : FOUR [PRODUCER] published event : FOUR new SynchronousQueue(boolean fair).
Ce que vous devez retenir à propos de SynchronousQueue en Java.

Voici quelques propriétés importantes de ce type spécial de file d’attente de blocage en Java. Il est très utile de transmettre des données d'un thread à un autre de manière synchronisée. Cette file d'attente n'a pas de capacité et est bloquée jusqu'à ce qu'un autre thread la libère.

  1. SynchronousQueue bloque, et jusqu'à ce qu'un thread soit prêt à prendre des données, un autre essaiera de mettre des données.
  2. SynchronousQueue n'a pas de volume. Autrement dit, il ne contient pas de données.
  3. SynchronousQueue est utilisé pour implémenter une stratégie de mise en file d'attente, dans laquelle un thread passe le contrôle à un thread en attente, ou en crée un nouveau s'il est autorisé, sinon le contrôle n'est pas transféré.
  4. Cette file d'attente n'autorise pas les données nulles. Une tentative d'ajout d'un élément nul lancera une NullPointerException .
  5. Si vous utilisez d'autres méthodes de Collection (telles que contain), SynchronousQueue se comporte comme une collection vide.
  6. Vous ne pouvez pas utiliser la méthode peek de SynchronousQueue car l'élément n'existe que lorsque vous essayez de le supprimer ; De plus, vous ne pourrez pas insérer d'éléments (en utilisant n'importe quelle méthode) jusqu'à ce qu'un autre thread tente de les supprimer.
  7. Vous ne pourrez pas utiliser l'itérateur pour SynchronousQueue car... il n'a aucun élément.
  8. SynchronousQueue peut être créé avec des règles équitables, où l'accès aux threads est garanti dans l'ordre FIFO.
Il s’agit peut-être de SynchronousQueue en Java. Nous avons examiné certaines des fonctionnalités spéciales de cette collection multithread et appris comment résoudre le problème classique producteur-consommateur à l'aide de SynchronousQueue en Java. À propos, l'appeler une file d'attente n'est pas tout à fait correct, car... il ne contient aucun élément. L'appel à put() ne se terminera pas tant qu'un autre thread n'appellera pas take(). Il est plus correct de le considérer comme un lieu de rencontre de fils, où ils partagent un objet. En d’autres termes, il s’agit d’un utilitaire de transmission synchronisée d’objets en Java, peut-être une alternative plus sûre à la méthode wait and notify .
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION