Servicio de mensajes inferiores de Java

1. Cola de bloqueo

BlockingQueue también es una interfaz bajo java.util.concurrent, que resuelve el problema de cómo transmitir datos de manera eficiente en subprocesos múltiples A través de estas clases eficientes y seguras para subprocesos, podemos construir programas multiproceso de alta calidad.

Una herramienta que se utiliza principalmente para controlar la sincronización de hilos. BlockingQueue es una interfaz y los métodos que contiene son los siguientes:

La interfaz pública BlockingQueue <E> extiende la cola <E> { 
 boolean add (E e);
 

 oferta booleana (E e);

 void put (E e) lanza InterruptedException;

 oferta booleana (E e, tiempo de espera largo, unidad TimeUnit);

 E take () lanza InterruptedException;

 Encuesta E (tiempo de espera prolongado, unidad TimeUnit);

 int capacidadRestante ();

 booleano eliminar (Objeto o);

 public boolean contiene (Objeto o);

 int drenajeTo (Colección <? super E> c);

 int drenajeTo (Colección <? super E> c, int maxElements); }

  • insertar:

  • 1) agregar (anObject): Agregar objeto a BlockingQueue, es decir, si BlockingQueue puede adaptarse, devuelve verdadero; de lo contrario, se lanza una excepción, lo cual no es bueno

  • 2) oferta (anObject): Significa que si es posible, agregue el Objeto al BlockingQueue, es decir, si el BlockingQueue puede acomodar, devuelve verdadero, de lo contrario devuelve falso.

  • 3) put (anObject): agrega unObject a BlockingQueue. Si BlockQueue no tiene espacio, el hilo que llama a este método será bloqueado hasta que haya espacio en BlockingQueue para continuar. Si hay bloqueo, esperará si puedes ' t ponerlo.

  • Leer:

  • 4) poll (time): quita el primer objeto en BlockingQueue. Si no puedes quitarlo inmediatamente, puedes esperar el tiempo especificado por el parámetro time, y devolver nulo si no puedes obtenerlo; si no puedes conseguirlo, devuelve nulo

  • 5) take (): Toma el primer objeto en BlockingQueue. Si el BlockingQueue está vacío, bloquéalo y entra en el estado de espera hasta que Blocking tenga un nuevo objeto agregado; bloquea, espera si no puedes obtenerlo

  • otro

  • int residentCapacity (); Devuelve la capacidad restante de la cola, que se utiliza al insertar y recuperar la cola. Los datos pueden ser inexactos.

  • boolean remove (Object o); Elimina un elemento de la cola, si existe, elimina uno o más, la cola se cambia y devuelve verdadero

  • public boolean contiene (Objeto o); Verifique si este elemento existe en la cola, devuelva verdadero si existe

  • int DrainTo (Colección c); Elimina todos los elementos disponibles en esta cola y agrégalos a la colección dada. (Es decir, sácalo y ponlo en la colección)

  • int drenajeTo (Colección c, int maxElements); La diferencia con el método anterior es que se especifica el número de movimientos; (saca el número especificado y ponlo en la colección)

  • Los métodos principales son: poner, tomar un par de acceso de bloqueo; agregar, sondear un par de acceso sin bloqueo. Como se mencionó anteriormente, BlockingQueue es una interfaz. Tiene cuatro clases de implementación específicas, dos de las cuales se usan comúnmente:

  • 1. ArrayBlockingQueue: Una cola de bloqueo limitada soportada por una matriz, una BlockingQueue con un tamaño específico, y su constructor debe tomar un parámetro int para indicar su tamaño.Los objetos que contiene se ordenan en orden FIFO (primero en entrar, primero en salir).

  • 2. LinkedBlockingQueue: BlockingQueue de tamaño variable, la capacidad se puede especificar en el constructor, o no se especifica, si no se especifica, el máximo predeterminado es Integer.MAX_VALUE, del cual se utilizan principalmente los métodos put y take. El método put será se usa cuando la cola está llena. Bloqueo hasta que se consume un miembro de la cola, el método de toma se bloqueará cuando la cola esté vacía, hasta que se coloque un miembro de la cola.

  • La diferencia entre LinkedBlockingQueue y ArrayBlockingQueue:

  • Al comparar LinkedBlockingQueue y ArrayBlockingQueue, la estructura de datos utilizada detrás de ellos es diferente, lo que hace que el rendimiento de datos de LinkedBlockingQueue sea mayor que el de ArrayBlockingQueue, pero la previsibilidad de su rendimiento es menor que la de ArrayBlockingQueue cuando el número de subprocesos es grande.

  • Los siguientes son ejemplos de productores y consumidores implementados con BlockingQueue:

  • Producto productor:

 

El producto de clase pública implementa la cola Runnable {BlockingQueue <String>;

 public Product (BlockingQueue <String> queue) {// Al crear un objeto, pase una cola de bloqueo this.queue = queue;}

 @Override public void run () {try {System.out.println (Thread.currentThread (). GetName () + "iniciar producción"); String temp = Thread.currentThread (). GetName () + ": hilo de producción" ; queue.put (temp); // Pon los datos en la cola, si la cola está llena, el hilo actual se bloqueará} catch (InterruptedException e) {e.printStackTrace ();}}}

Consumidor:

 

El consumidor de clase pública implementa la cola Runnable {BlockingQueue <String>;

 Public Consumer (BlockingQueue <String> queue) {// El propósito de usar el constructor parametrizado es que puedo pasar una cola cuando creo el objeto consumidor 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 () + "Listo para consumir ..."); String temp = queue.take (); // Sacar el consumo de tareas de la cola. Si la cola está vacía, bloqueará el hilo actual System.out.println (Thread.currentThread () .getName () + "Obtener tarea de trabajo ====" + temp);}} catch (InterruptedException e) {e.printStackTrace ();}}}

Clase de prueba TestQueue:

clase pública TestQueue { 
 public static void main (String [] args) { 
  // 新建 一个 阻塞 队列 , 队列 长度 是 5 
  BlockingQueue <String> cola = new LinkedBlockingDeque <String> (5); 
  // BlockingQueue <String> cola = new ArrayBlockingQueue <String> (5); 
  Consumidor consumidor = nuevo consumidor (cola); 
  Producto producto = nuevo producto (cola); 
  for (int i = 0; i <3; i ++) { 
   new Thread (producto, "producto" + i) .start (); 
  } 
  // for (int i = 0; i <5; i ++) { 
  // new Thread (consumidor, "consumidor"). start (); 
  //} 
 } 
}

Todo el conjunto de código significa inicializar una cola de mensajes con el tipo String en ella, la longitud de la cola es 5, el hilo del productor se usa para simular la solicitud de tres usuarios, los datos de la solicitud del usuario se colocan temporalmente en la cola BlockingQueue y luego el consumidor el subproceso continúa Tome tareas de la cola para el procesamiento de la lógica empresarial hasta que no quede nada para consumir en la cola. Puede verse que la cola de mensajes tiene dos características principales: desacoplamiento y recorte de picos y relleno de valles. No hay relación entre el productor y el consumidor. El productor pone datos en la cola y el consumidor toma datos de la cola. Todos establecen una relación con la cola y se desacoplan; si la concurrencia del productor es alta, simplemente pone los datos en primer lugar. En la cola, los consumidores pueden comer lentamente, pero en realidad, el servidor no se abrumará de inmediato. Dirección de referencia: http://blog.csdn.net/ghsau/article/details/8108292

2. Servicio de mensajes Java

2.1 Introducción a JMS

JMS, o Java Message Service, se utiliza para enviar mensajes entre dos aplicaciones o en un sistema distribuido para la comunicación asíncrona. JMS es una API independiente del proveedor (o plataforma). Similar a JDBC (Java Database Connectivity): aquí, JDBC es una API que se puede utilizar para acceder a muchas bases de datos relacionales diferentes, mientras que JMS proporciona el mismo método de acceso independiente del proveedor para acceder a los servicios de mensajería. Muchos proveedores admiten JMS, incluidos MQSeries de IBM, el servicio Weblogic JMS de BEA, SonicMQ de Progress, etc. JMS le permite enviar mensajes de un cliente JMS a otro a través de servicios de mensajería. Un mensaje es un tipo de objeto en JMS, que consta de dos partes: un encabezado y un cuerpo del mensaje. El encabezado consta de información de enrutamiento y metadatos sobre el mensaje; el cuerpo del mensaje lleva los datos o la carga útil de la aplicación. Según el tipo de carga útil, los mensajes se pueden dividir en varios tipos, que contienen: texto simple (TextMessage), objeto serializable (ObjectMessage), colección de atributos (MapMessage), flujo de bytes (BytesMessage), flujo de valor primitivo (StreamMessage) y mensaje sin carga útil (Mensaje).

2.2 Composición de JMS

JMS consta de los siguientes elementos: Proveedor de JMS: un middleware orientado a mensajes, una implementación de la especificación JMS. El proveedor puede ser una implementación JMS de la plataforma Java o un adaptador de middleware orientado a mensajes para una plataforma que no sea Java. Cliente JMS: produce o consume aplicaciones u objetos Java basados ​​en mensajes (es decir, los productores y consumidores se denominan colectivamente clientes JMS). Productor de JMS: un cliente de JMS que crea y envía mensajes. Consumidor JMS: el cliente JMS que recibe el mensaje. Mensaje JMS: un objeto que puede transferir datos entre clientes JMS Cola JMS: un área que contiene los mensajes que se envían y esperan ser leídos. Si se lee un mensaje, se eliminará de la cola. Tema JMS: mecanismo que da soporte al envío de mensajes a varios suscriptores.

2.3 Modelo de servicio de mensajes Java

  • Modelo de punto a punto En el modelo de cola de punto a punto, un productor publica mensajes en una cola específica y un consumidor lee los mensajes de la cola. Aquí, el productor conoce la cola del consumidor y envía el mensaje directamente a la cola del consumidor. Este modo tiene las siguientes características: Solo un consumidor recibirá el mensaje; el productor no necesita que el consumidor esté en el estado de ejecución durante el consumo del mensaje, y el consumidor tampoco necesita estar en el estado de ejecución cuando el el productor está enviando el mensaje; todo éxito Todos los mensajes procesados ​​están firmados por el consumidor.

  • El modelo de editor / suscriptor El modelo de editor / suscriptor admite la publicación de mensajes en un tema de mensaje específico. En este modelo, los editores y los suscriptores no se conocen entre sí, similar a un tablero de anuncios anónimo. Este modelo tiene las siguientes características: múltiples consumidores pueden obtener mensajes; existe una dependencia temporal entre editores y suscriptores. Los editores deben crear una suscripción (suscripción) para que los consumidores puedan suscribirse. Los suscriptores deben mantener un estado activo continuo para recibir mensajes, a menos que el suscriptor establezca una suscripción duradera.

2.4 Cola de mensajes (ActiveMQ)

ActiveMQ es una implementación de la especificación JMS, a continuación se explica cómo utilizar

  • Descargue ActiveMQ y vaya al sitio web oficial para descargar: http://activemq.apache.org/

  • Ejecute ActiveMQ para descomprimir apache-activemq-5.5.1-bin.zip (similar a Tomcat, se puede usar después de la descompresión). Algunas personas que busqué en Internet modificaron la dirección de conexión y el protocolo en el archivo de configuración activeMQ.xml. estaba probando La prueba puede ser exitosa sin modificaciones. Si su prueba no es exitosa, puede modificarla de la siguiente manera:

<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>

El código de prueba es el siguiente: Producto de productor:

 

Producto de clase pública {nombre de usuario de cadena privada = ActiveMQConnectionFactory.DEFAULT_USER; contraseña de cadena privada = ActiveMQConnectionFactory.DEFAULT_PASSWORD; url de cadena privada = ActiveMQConnectionFactory.DEFAULT_BROKER_URL; conexión de conexión privada = nulo; sesión de sesión privada = nula; Private String subject = "myQueue"; destino de destino privado = nulo; productor de MessageProducer privado = nulo;

 / ** * @Description 初始化 方法 * @Author 刘俊 重 * @Date 2017/12/20 * / private void init () lanza JMSException {ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory (nombre de usuario, contraseña, url); conexión = connectionFactory.createConnection (); sesión = conexión.createSession (falso, Sesión.AUTO_ACKNOWLEDGE); destino = session.createQueue (asunto); productor = session.createProducer (destino); productor.setDeliveryMode (DeliveryMode.NON_PERSISTENT); }

 public void productMessage (String message) lanza JMSException {this.init (); TextMessage textMessage = session.createTextMessage (mensaje); connection.start (); System.out.println ("El productor está listo para enviar un mensaje:" + textMessage); producer.send (textMessage); System.out.println ("El productor ha enviado el mensaje ...");}

 public void close () lanza JMSException {System.out.println ("生产者 开始 关闭 连接"); if (nulo! = productor) {productor.close (); } if (null! = session) {session.close (); } if (nulo! = conexión) {conexión.close (); }}}

Consumidor:

 

El consumidor de clase pública implementa MessageListener, ExceptionListener {nombre de cadena privada = ActiveMQConnectionFactory.DEFAULT_USER; contraseña de cadena privada = ActiveMQConnectionFactory.DEFAULT_PASSWORD; url de cadena privada = ActiveMQConnectionFactory.DEFAULT_BROKER_URL; private ActiveMQConnectionFactory connectionFactory = null; conexión de conexión privada = nulo; sesión de sesión privada = nula; Private String subject = "myQueue"; destino de destino privado = nulo; consumidor de MessageConsumer privado = nulo; public static Boolean isconnection = false;

 / ** * @Description 连接 ActiveMQ * @Author 刘俊 重 * @Date 2017/12/20 * / private void init () lanza JMSException {connectionFactory = new ActiveMQConnectionFactory (nombre, contraseña, url); conexión = connectionFactory.createConnection (); sesión = conexión.createSession (falso, Sesión.AUTO_ACKNOWLEDGE); destino = session.createQueue (asunto); consumidor = session.createConsumer (destino); }

 public void consumerMessage () throws JMSException {this.init (); connection.start (); // Configurar la supervisión de mensajes y la supervisión de excepciones consumer.setMessageListener (this); connection.setExceptionListener (this); System.out.println (" consumo La persona empieza a escuchar ... "); isconnection = true; // Mensaje recibe = consumer.receive ();}

 public void close () lanza JMSException {if (null! = consumidor) {consumer.close (); } if (null! = session) {session.close (); } if (nulo! = conexión) {conexión.close (); }}

 / ** * Función de manejo de excepciones * / @Override public void onException (excepción JMSException) {// La conexión se cierra debido a una excepción isconnection = false;}

 / ** * Función de procesamiento de mensajes * / @Override public void onMessage (Mensaje de mensaje) {try {if (instancia de mensaje de TextMessage) {TextMessage textMsg = (TextMessage) mensaje; String text = textMsg.getText (); System.out.println ("El mensaje recibido por el consumidor =======" + texto);} else {System.out.println ("El mensaje recibido no cumple");}} catch (JMSException e) {e.printStackTrace ();}}}

Nota: Los consumidores deben implementar MessageListener y ExceptionListener para monitorear el manejo de mensajes y errores. Producto de prueba de la clase de prueba del productor:

TestProduct de clase pública { 
 public static void main (String [] args) lanza JMSException { 
  for (int i = 0; i <100; i ++) { 
   Product product = new Product (); 
   product.productMessage ("¡Hola mundo!" + i); 
   product.close (); 
  } 
 } 
}

TestProduct se utiliza para simular la generación de 100 mensajes y escribirlos en la cola de ActiveMQ. Clase de prueba de consumidor TestConsumer:

 

TestConsumer de clase pública implementa Runnable {subproceso estático hilo = nulo;

 public static void main (String [] args) throws InterruptedException {thread = new Thread (new TestConsumer ()); thread.start (); while (true) {// Escuche la cola de mensajes en todo momento, y si el hilo muere, crea uno nuevo Thread boolean alive = thread.isAlive (); System.out.println ("Estado actual del hilo:" + vivo); if (! alive) {thread = new Thread (new TestConsumer ()); thread .start (); System .out.println ("Reinicio del hilo completo");} Thread.sleep (1000);}}

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

TestConsumer utiliza varios subprocesos aquí para garantizar que haya un subproceso vivo esperando recibir la cola de mensajes de ActiveMQ y llamar al consumidor para su procesamiento.

Resumen: Tengo entendido que la comunicación entre subprocesos utiliza colas, como BlockingQueue, y la comunicación entre procesos utiliza JMS, como ActiveMQ.

Se adjunta un artículo sobre colas de mensajes escrito por el 58 arquitecto Shen Jian, que se puede utilizar como referencia: http://dwz.cn/78yLxL

Lo que se debe enfatizar es que la cotización de cualquier tecnología debe servir para resolver problemas comerciales, no solo para mostrar habilidades. Por ejemplo, tome los servicios de mensajería. Por ejemplo, un usuario se registra en un determinado sitio web. Después de registrarme, debo llamar al servicio de correo electrónico y SMS para enviarle una notificación. También puedo usar la información que completó para recomendar a alguien que podría Usuarios, entonces el negocio principal aquí es el registro, otros usuarios de notificación y recomendación pueden procesarse en la cola de mensajes, primero responder a la información de registro y luego llamar a otros servicios para manejar los dos servicios de usuarios de notificación y recomendación. Sin embargo, la cantidad de usuarios en la etapa inicial del sitio web puede ser relativamente pequeña y mis necesidades pueden satisfacerse sin colas de mensajes. El uso de colas de mensajes aumentará la complejidad del proyecto. Por lo tanto, el uso de nuevas tecnologías debe resolver problemas comerciales , en lugar de simplemente mostrar sus habilidades. Documento de referencia: http://blog.csdn.net/fanzhigang0/article/details/43764121http://blog.csdn.net/u010702229/article/details/18085263

Supongo que te gusta

Origin blog.csdn.net/keepfriend/article/details/113859444
Recomendado
Clasificación