Service de messagerie Java bottom

1. Blocage de la file d'attente

BlockingQueue est également une interface sous java.util.concurrent, qui résout le problème de la transmission efficace des données en multithreading. Grâce à ces classes efficaces et thread-safe, nous pouvons créer des programmes multithread de haute qualité.

Un outil principalement utilisé pour contrôler la synchronisation des threads. BlockingQueue est une interface, et les méthodes à l'intérieur sont les suivantes:

interface publique BlockingQueue <E> étend la file d'attente <E> { 
 ajout booléen (E e);
 

 offre booléenne (E e);

 void put (E e) lance InterruptedException;

 offre booléenne (E e, long timeout, unité TimeUnit);

 E take () lance InterruptedException;

 Sondage E (long timeout, unité TimeUnit);

 int restantCapacité ();

 booléen remove (Object o);

 public boolean contient (Object o);

 int drainTo (Collection <? super E> c);

 int drainTo (Collection <? super E> c, int maxElements); }

  • insérer:

  • 1) add (anObject): Ajouter un objet à BlockingQueue, c'est-à-dire que si BlockingQueue peut accueillir, il retourne true, sinon une exception est levée, ce qui n'est pas bon

  • 2) offer (anObject): Cela signifie que si possible, ajoutez l'objet à BlockingQueue, c'est-à-dire que si BlockingQueue peut accueillir, il retourne true, sinon il retourne false.

  • 3) put (anObject): ajoutez un objet au BlockingQueue. Si le BlockQueue n'a pas d'espace, le thread appelant cette méthode sera bloqué jusqu'à ce qu'il y ait de la place dans le BlockingQueue pour continuer. S'il y a blocage, il attendra si vous le pouvez ' t le mettre.

  • Lis:

  • 4) poll (time): Supprimez le premier objet de BlockingQueue. Si vous ne pouvez pas le retirer immédiatement, vous pouvez attendre l'heure spécifiée par le paramètre time, et renvoyer null si vous ne pouvez pas l'obtenir; si vous ne pouvez pas l'obtenir, retournez null

  • 5) take (): Prenez le premier objet dans BlockingQueue. Si BlockingQueue est vide, bloquez-le et entrez dans l'état d'attente jusqu'à ce que Blocking ait un nouvel objet ajouté; bloquez, attendez si vous ne pouvez pas l'obtenir

  • autre

  • int restantCapacity (); Renvoie la capacité restante de la file d'attente, qui est utilisée lors de l'insertion et de la récupération de la file d'attente. Les données peuvent être inexactes.

  • boolean remove (Object o); Supprimer un élément de la file d'attente, s'il existe, en supprimer un ou plusieurs, la file d'attente est modifiée et renvoie true

  • public boolean contains (Object o); Vérifie si cet élément existe dans la file d'attente, renvoie true s'il existe

  • int drainTo (Collection c); Supprimez tous les éléments disponibles dans cette file d'attente et ajoutez-les à la collection donnée. (Autrement dit, sortez-le et mettez-le dans la collection)

  • int drainTo (Collection c, int maxElements); La différence avec la méthode ci-dessus est que le nombre de coups est spécifié; (retirer le nombre spécifié et le mettre dans la collection)

  • Les principales méthodes sont: mettre, prendre une paire d'accès bloquant; ajouter, interroger une paire d'accès non bloquant. Comme mentionné ci-dessus, BlockingQueue est une interface. Elle comporte quatre classes d'implémentation spécifiques, dont deux sont couramment utilisées:

  • 1. ArrayBlockingQueue: une file d'attente de blocage bornée prise en charge par un tableau, une BlockingQueue avec une taille spécifiée et son constructeur doit prendre un paramètre int pour indiquer sa taille. Les objets qu'il contient sont triés dans l'ordre FIFO (premier entré, premier sorti).

  • 2. LinkedBlockingQueue: BlockingQueue de taille variable, la capacité peut être spécifiée dans le constructeur, ou non spécifiée, si non spécifiée, le maximum par défaut est Integer.MAX_VALUE, dont les méthodes put et take sont principalement utilisées. La méthode put sera Utilisée lorsque la file d'attente est pleine. En bloquant jusqu'à ce qu'un membre de file d'attente soit consommé, la méthode take se bloque lorsque la file d'attente est vide, jusqu'à ce qu'un membre de file d'attente soit inséré.

  • La différence entre LinkedBlockingQueue et ArrayBlockingQueue:

  • En comparant LinkedBlockingQueue et ArrayBlockingQueue, la structure de données utilisée derrière eux est différente, ce qui entraîne un débit de données de LinkedBlockingQueue supérieur à celui d'ArrayBlockingQueue, mais la prévisibilité de ses performances est inférieure à celle d'ArrayBlockingQueue lorsque le nombre de threads est important.

  • Voici des exemples de producteurs et de consommateurs implémentés avec BlockingQueue:

  • Produit producteur:

 

public class Le produit implémente la file d'attente Runnable {BlockingQueue <String>;

 public Product (BlockingQueue <String> queue) {// Lors de la création d'un objet, passez dans une file d'attente de blocage this.queue = queue;}

 @Override public void run () {try {System.out.println (Thread.currentThread (). GetName () + "start production"); String temp = Thread.currentThread (). GetName () + ": fil de production" ; queue.put (temp); // Mettre les données dans la file d'attente, si la file d'attente est pleine, le thread actuel sera bloqué} catch (InterruptedException e) {e.printStackTrace ();}}}

Consommateur:

 

public class Consumer implémente la file d'attente Runnable {BlockingQueue <String>;

 public Consumer (BlockingQueue <String> queue) {// Le but de l'utilisation du constructeur paramétré est que je peux passer dans une file d'attente lorsque je crée l'objet consommateur this.queue = queue;}

 @Override public void run () {Random random = new Random (); try {while (true) {Thread.sleep (random.nextInt (10)); System.out.println (Thread.currentThread (). GetName () + "Prêt à consommer ..."); String temp = queue.take (); // Retire la consommation de tâche de la file d'attente. Si la file d'attente est vide, elle bloquera le thread actuel System.out.println (Thread.currentThread () .getName () + "Obtenir la tâche de travail ====" + temp);}} catch (InterruptedException e) {e.printStackTrace ();}}}

Classe de test TestQueue:

public class TestQueue { 
 public static void main (String [] args) { 
  // 新建 一个 阻塞 队列 , 队列 长度 是 5 
  BlockingQueue <String> queue = new LinkedBlockingDeque <String> (5); 
  // BlockingQueue <String> queue = new ArrayBlockingQueue <String> (5); 
  Consommateur consommateur = nouveau consommateur (file d'attente); 
  Produit produit = nouveau produit (file d'attente); 
  for (int i = 0; i <3; i ++) { 
   new Thread (product, "product" + i) .start (); 
  } 
  // for (int i = 0; i <5; i ++) { 
  // new Thread (consumer, "consumer"). start (); 
  //} 
 } 
}

L'ensemble du code signifie initialiser une file d'attente de messages avec le type String, la longueur de la file d'attente est de 5, le thread producteur est utilisé pour simuler trois utilisateurs demandant, les données de la demande de l'utilisateur sont temporairement placées dans la file d'attente BlockingQueue, puis le consommateur thread continue Prenez des tâches de la file d'attente pour le traitement de la logique métier jusqu'à ce qu'il ne reste plus rien à consommer dans la file d'attente. On constate que la file d'attente de messages présente deux caractéristiques majeures: le découplage et l'écrêtage des pics et le remplissage des vallées. Il n'y a pas de relation entre le producteur et le consommateur. Le producteur place les données dans la file d'attente et le consommateur prend les données de la file d'attente. Ils établissent tous une relation avec la file d'attente et se découplent; si la concurrence d'accès du producteur est élevée, il suffit met les données en premier. Dans la file d'attente, les consommateurs peuvent manger lentement, mais en réalité, le serveur ne sera pas submergé immédiatement. Adresse de référence: http://blog.csdn.net/ghsau/article/details/8108292

2. Service de messagerie Java

2.1 Introduction à JMS

JMS, ou Java Message Service, est utilisé pour envoyer des messages entre deux applications ou dans un système distribué pour une communication asynchrone. JMS est une API indépendante du fournisseur (ou de la plate-forme). Similaire à JDBC (Java Database Connectivity): ici, JDBC est une API qui peut être utilisée pour accéder à de nombreuses bases de données relationnelles différentes, tandis que JMS fournit la même méthode d'accès indépendante du fournisseur pour accéder aux services de messagerie. De nombreux fournisseurs prennent en charge JMS, notamment MQSeries d'IBM, le service Weblogic JMS de BEA, SonicMQ de Progress, etc. JMS vous permet d'envoyer des messages d'un client JMS à un autre via les services de messagerie. Un message est un type d'objet dans JMS, qui se compose de deux parties: un en-tête et un corps de message. L'en-tête se compose d'informations de routage et de métadonnées sur le message; le corps du message transporte les données ou la charge utile de l'application. Selon le type de charge utile, les messages peuvent être divisés en plusieurs types, qui transportent: texte simple (TextMessage), objet sérialisable (ObjectMessage), collection d'attributs (MapMessage), flux d'octets (BytesMessage), flux de valeur primitif (StreamMessage), et message sans charge utile (Message).

2.2 Composition de JMS

JMS se compose des éléments suivants: Fournisseur de fournisseur JMS: un middleware orienté message, une implémentation de la spécification JMS. Le fournisseur peut être une implémentation JMS de la plate-forme Java ou un adaptateur middleware orienté message pour une plate-forme non Java. Client JMS: produit ou utilise des applications ou des objets Java basés sur des messages (c'est-à-dire que les producteurs et les consommateurs sont collectivement appelés clients JMS). Producteur JMS: un client JMS qui crée et envoie des messages. Consommateur JMS: client JMS qui reçoit le message. Message JMS: un objet qui peut transférer des données entre des clients JMS File d'attente JMS: une zone qui contient les messages envoyés et en attente de lecture. Si un message est lu, il sera supprimé de la file d'attente. Rubrique JMS: mécanisme qui prend en charge l'envoi de messages à plusieurs abonnés.

2.3 Modèle de service de messagerie Java

  • Modèle point à point Dans le modèle de file d'attente point à point, un producteur publie des messages dans une file d'attente spécifique et un consommateur lit les messages de la file d'attente. Ici, le producteur connaît la file d'attente du consommateur et envoie le message directement à la file d'attente du consommateur. Ce mode présente les caractéristiques suivantes: un seul consommateur recevra le message; le producteur n'a pas besoin que le consommateur soit en état d'exécution pendant la consommation du message, et le consommateur n'a pas non plus besoin d'être en état d'exécution lorsque le le producteur envoie le message; chaque succès Tous les messages traités sont signés par le consommateur.

  • Le modèle éditeur / abonné Le modèle éditeur / abonné prend en charge la publication de messages dans une rubrique de message spécifique. Dans ce modèle, les éditeurs et les abonnés ne se connaissent pas, à l'instar d'un babillard anonyme. Ce modèle présente les caractéristiques suivantes: plusieurs consommateurs peuvent obtenir des messages; il existe une dépendance temporelle entre les éditeurs et les abonnés. Les éditeurs doivent créer un abonnement (abonnement) afin que les consommateurs puissent s'abonner. Les abonnés doivent maintenir un état actif continu pour recevoir des messages, à moins que l'abonné n'établisse un abonnement durable.

2.4 File d'attente de messages (ActiveMQ)

ActiveMQ est une implémentation de la spécification JMS, voici comment utiliser

  • Téléchargez ActiveMQ et rendez-vous sur le site officiel pour télécharger: http://activemq.apache.org/

  • Exécutez ActiveMQ pour décompresser apache-activemq-5.5.1-bin.zip (similaire à Tomcat, il peut être utilisé après décompression). Certaines personnes que j'ai recherchées sur Internet ont modifié l'adresse de connexion et le protocole dans le fichier de configuration activeMQ.xml. I was testing Le test peut réussir sans modification. Si votre test échoue, vous pouvez modifier comme suit:

<transportConnectors> 
<transportConnector name = "openwire" uri = "tcp: // localhost: 61616" /> 
<transportConnector name = "ssl" uri = "ssl: // localhost: 61617" /> 
<transportConnector name = "stomp" uri = "stomp: // localhost: 61613" /> 
<transportConnector uri = "http: // localhost: 8081" /> 
<transportConnector uri = "udp: // localhost: 61618" />
</transportConnectors>

Le code de test est le suivant: Produit producteur:

 

classe publique Product {private String username = ActiveMQConnectionFactory.DEFAULT_USER; mot de passe de chaîne privé = ActiveMQConnectionFactory.DEFAULT_PASSWORD; chaîne privée url = ActiveMQConnectionFactory.DEFAULT_BROKER_URL; connexion de connexion privée = null; session de session privée = null; private String subject = "maQueue"; destination de destination privée = null; producteur de MessageProducer privé = null;

 / ** * @Description 初始化 方法 * @Author 刘俊 重 * @Date 2017/12/20 * / private void init () jette JMSException {ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory (nom d'utilisateur, mot de passe, url); connection = connectionFactory.createConnection (); session = connection.createSession (false, Session.AUTO_ACKNOWLEDGE); destination = session.createQueue (sujet); producteur = session.createProducer (destination); producteur.setDeliveryMode (DeliveryMode.NON_PERSISTENT); }

 public void productMessage (String message) jette JMSException {this.init (); TextMessage textMessage = session.createTextMessage (message); connection.start (); System.out.println ("Le producteur est prêt à envoyer un message:" + textMessage); producteur.send (textMessage); System.out.println ("Le producteur a envoyé le message ...");}

 public void close () lance JMSException {System.out.println ("生产者 开始 关闭 连接"); if (null! = producteur) {producteur.close (); } if (null! = session) {session.close (); } if (null! = connexion) {connection.close (); }}}

Consommateur:

 

public class Consumer implémente MessageListener, ExceptionListener {private String name = ActiveMQConnectionFactory.DEFAULT_USER; mot de passe de chaîne privé = ActiveMQConnectionFactory.DEFAULT_PASSWORD; chaîne privée url = ActiveMQConnectionFactory.DEFAULT_BROKER_URL; private ActiveMQConnectionFactory connectionFactory = null; connexion de connexion privée = null; session de session privée = null; private String subject = "maQueue"; destination de destination privée = null; consommateur MessageConsumer privé = null; public static Boolean isconnection = false;

 / ** * @Description 连接 ActiveMQ * @Author 刘俊 重 * @Date 2017/12/20 * / private void init () jette JMSException {connectionFactory = new ActiveMQConnectionFactory (nom, mot de passe, url); connection = connectionFactory.createConnection (); session = connection.createSession (false, Session.AUTO_ACKNOWLEDGE); destination = session.createQueue (sujet); consommateur = session.createConsumer (destination); }

 public void consumerMessage () throws JMSException {this.init (); connection.start (); // Configurer la surveillance des messages et la surveillance des exceptions consumer.setMessageListener (this); connection.setExceptionListener (this); System.out.println (" consommation La personne commence à écouter ... "); isconnection = true; // Message receive = consumer.receive ();}

 public void close () lance JMSException {if (null! = consommateur) {consumer.close (); } if (null! = session) {session.close (); } if (null! = connexion) {connection.close (); }}

 / ** * Fonction de gestion des exceptions * / @Override public void onException (exception JMSException) {// La connexion est fermée en raison d'une exception isconnection = false;}

 / ** * Fonction de traitement des messages * / @Override public void onMessage (Message message) {try {if (message instanceof TextMessage) {TextMessage textMsg = (TextMessage) message; String text = textMsg.getText (); System.out.println ("Le message reçu par le consommateur =======" + texte);} else {System.out.println ("Le message reçu ne correspond pas");}} catch (JMSException e) {e.printStackTrace ();}}}

Remarque: les consommateurs doivent implémenter MessageListener et ExceptionListener pour surveiller la gestion des messages et des erreurs. Classe de test du producteur TestProduct:

public class TestProduct { 
 public static void main (String [] args) lance JMSException { 
  for (int i = 0; i <100; i ++) { 
   Product product = new Product (); 
   product.productMessage ("Bonjour le monde!" + i); 
   product.close (); 
  } 
 } 
}

TestProduct est utilisé pour simuler la génération de 100 messages et les écrire dans la file d'attente ActiveMQ. Classe de test consommateur TestConsumer:

 

La classe publique TestConsumer implémente Runnable {thread de thread statique = null;

 public static void main (String [] args) jette InterruptedException {thread = new Thread (new TestConsumer ()); thread.start (); while (true) {// Écoutez la file d'attente des messages à tout moment, et si le thread meurt, créez-en un nouveau Thread boolean live = thread.isAlive (); System.out.println ("Current thread status:" + alive); if (! alive) {thread = new Thread (new TestConsumer ()); thread .start (); System .out.println ("Redémarrage du thread terminé");} Thread.sleep (1000);}}

 @Override public void run () {try {Consumer consumer = new Consumer (); consumer.consumerMessage (); while (Consumer.isconnection) {// System.out.println (123); }} catch (JMSException e) {e.printStackTrace (); }}}

TestConsumer utilise ici plusieurs threads pour s'assurer qu'il existe un thread actif en attente de recevoir la file d'attente de messages ActiveMQ et d'appeler le consommateur pour traitement.

Résumé: Je crois comprendre que la communication inter-thread utilise une file d'attente, telle que BlockingQueue, et la communication inter-processus utilise JMS, telle qu'ActiveMQ.

Vous trouverez ci-joint un article sur les files d'attente de messages rédigé par l'architecte 58 Shen Jian, qui peut être utilisé comme référence: http://dwz.cn/78yLxL

Ce qu'il faut souligner, c'est que la cotation de toute technologie doit servir à résoudre des problèmes commerciaux, pas seulement montrer des compétences. Prenons l'exemple des services de messagerie. Par exemple, un utilisateur s'inscrit sur un certain site Web. Après l'inscription, je dois appeler le service de messagerie et de SMS pour lui envoyer une notification. Je peux également utiliser les informations qu'il a renseignées pour recommander quelqu'un qu'il pourrait Les utilisateurs, alors le cœur de métier ici est l'enregistrement, d'autres utilisateurs de notification et de recommandation peuvent être traités dans la file d'attente des messages, répondre d'abord aux informations d'enregistrement, puis appeler d'autres services pour gérer les deux services de notification et de recommandation d'utilisateurs. Cependant, le nombre d'utilisateurs au stade initial du site Web peut être relativement faible et mes besoins peuvent être satisfaits sans files d'attente de messages. L'utilisation de files d'attente de messages augmentera la complexité du projet. Par conséquent, l'utilisation de nouvelles technologies doit résoudre les problèmes commerciaux. , plutôt que de simplement montrer des compétences. Document de référence: http://blog.csdn.net/fanzhigang0/article/details/43764121http://blog.csdn.net/u010702229/article/details/18085263

Je suppose que tu aimes

Origine blog.csdn.net/keepfriend/article/details/113859444
conseillé
Classement