Java bottom message service

1. Blocking Queue

BlockingQueue is also an interface under java.util.concurrent, which solves the problem of how to efficiently transmit data in multithreading. Through these efficient and thread-safe classes, we can build high-quality multithreaded programs.

A tool mainly used to control thread synchronization. BlockingQueue is an interface, and the methods inside are as follows:

public interface BlockingQueue<E> extends Queue<E> {
 boolean add(E e);
 

 boolean offer(E e);

 void put(E e) throws InterruptedException;

 boolean offer(E e, long timeout, TimeUnit unit);

 E take() throws InterruptedException;

 E poll(long timeout, TimeUnit unit);

 int remainingCapacity();

 boolean remove(Object o);

 public boolean contains(Object o);

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

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

  • insert:

  • 1) add(anObject): Add Object to BlockingQueue, that is, if BlockingQueue can accommodate, it returns true, otherwise an exception is thrown, which is not good

  • 2) offer(anObject): It means that if possible, add the Object to the BlockingQueue, that is, if the BlockingQueue can accommodate, it returns true, otherwise it returns false.

  • 3) put(anObject): add anObject to the BlockingQueue. If the BlockQueue has no space, the thread calling this method will be blocked until there is room in the BlockingQueue to continue. If there is blockage, it will wait if you can't put it in.

  • Read:

  • 4) poll(time): Take away the first object in the BlockingQueue. If you can't take it out immediately, you can wait for the time specified by the time parameter, and return null if you can't get it; if you can't get it, return null

  • 5) take(): Take the first object in the BlockingQueue. If the BlockingQueue is empty, block it and enter the waiting state until Blocking has a new object added; block, wait if you can't get it

  • other

  • int remainingCapacity(); Returns the remaining capacity of the queue, which is used when inserting and retrieving the queue. The data may be inaccurate.

  • boolean remove(Object o); Remove an element from the queue, if it exists, remove one or more, the queue is changed and return true

  • public boolean contains(Object o); Check if this element exists in the queue, return true if it exists

  • int drainTo(Collection c); Remove all available elements in this queue and add them to the given collection. (That is, take it out and put it in the collection)

  • int drainTo(Collection c, int maxElements); The difference with the above method is that the number of moves is specified; (take out the specified number and put it in the collection)

  • The main methods are: put, take a pair of blocking access; add, poll a pair of non-blocking access. As mentioned above, BlockingQueue is an interface. It has four specific implementation classes, two of which are commonly used:

  • 1. ArrayBlockingQueue: A bounded blocking queue supported by an array, a BlockingQueue with a specified size, and its constructor must take an int parameter to indicate its size. The objects it contains are sorted in FIFO (first in, first out) order.

  • 2. LinkedBlockingQueue: BlockingQueue of variable size, the capacity can be specified in the constructor, or not specified, if not specified, the default maximum is Integer.MAX_VALUE, of which the put and take methods are mainly used. The put method will be used when the queue is full. Blocking until a queue member is consumed, the take method will block when the queue is empty, until a queue member is put in.

  • The difference between LinkedBlockingQueue and ArrayBlockingQueue:

  • Comparing LinkedBlockingQueue and ArrayBlockingQueue, the data structure behind them is different, resulting in the data throughput of LinkedBlockingQueue being greater than that of ArrayBlockingQueue, but the predictability of its performance is lower than that of ArrayBlockingQueue when the number of threads is large.

  • The following are examples of producers and consumers implemented with BlockingQueue:

  • Producer Product:

 

public class Product implements Runnable {  BlockingQueue<String> queue;

 public Product(BlockingQueue<String> queue) {// When creating an object, pass in a blocking queue this.queue = queue;}

 @Override public void run() {try {System.out.println(Thread.currentThread().getName() + "start production"); String temp = Thread.currentThread().getName() + ": production thread" ; queue.put(temp); // Put data in the queue, if the queue is full, the current thread will be blocked} catch (InterruptedException e) {e.printStackTrace();}}}

Consumer:

 

public class Consumer implements Runnable {  BlockingQueue<String> queue;

 public Consumer(BlockingQueue<String> queue) {// The purpose of using the parameterized constructor is that I can pass in a queue when I create the consumer object 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() + "Ready to consume..."); String temp = queue.take(); // Take task consumption from the queue. If the queue is empty, it will block the current thread System.out.println(Thread.currentThread().getName () + "Get work task ====" + temp);}} catch (InterruptedException e) {e.printStackTrace();}}}

Test class TestQueue:

public class TestQueue {
 public static void main(String[] args) {
  // Create a new blocking queue, the queue length is 5
  BlockingQueue<String> queue = new LinkedBlockingDeque<String>(5);
  // BlockingQueue<String> queue = new ArrayBlockingQueue<String>(5);
  Consumer consumer = new Consumer(queue);
  Product product = new Product(queue);
  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();
  // }
 }
}

The whole set of code means to initialize a message queue with String type in it, the queue length is 5, the producer thread is used to simulate three users requesting, the user's request data is temporarily placed in the BlockingQueue queue, and then the consumer thread continues Take tasks from the queue for business logic processing until there is nothing left to consume in the queue. It can be seen that the message queue has two major characteristics: decoupling and peak clipping and valley filling. There is no relationship between the producer and the consumer. The producer puts data in the queue, and the consumer takes data from the queue. They all establish a relationship with the queue and decouple; if the concurrency of the producer is high, it just puts the data first. In the queue, consumers can eat slowly, but in reality, the server will not be overwhelmed immediately. Reference address: http://blog.csdn.net/ghsau/article/details/8108292

2. Java Message Service

2.1 Introduction to JMS

JMS, or Java Message Service, is used to send messages between two applications or in a distributed system for asynchronous communication. JMS is a vendor (or platform) independent API. Similar to JDBC (Java Database Connectivity): Here, JDBC is an API that can be used to access many different relational databases, while JMS provides the same vendor-independent access method to access messaging services. Many vendors support JMS, including IBM's MQSeries, BEA's Weblogic JMS service, Progress's SonicMQ, and so on. JMS allows you to send messages from one JMS client to another through messaging services. A message is a type of object in JMS, which consists of two parts: a header and a message body. The header consists of routing information and metadata about the message; the body of the message carries the data or payload of the application. According to the type of payload, messages can be divided into several types, which carry: simple text (TextMessage), serializable object (ObjectMessage), attribute collection (MapMessage), byte stream (BytesMessage), primitive Value stream (StreamMessage), and message without payload (Message).

2.2 Composition of JMS

JMS consists of the following elements: JMS provider provider: a message-oriented middleware, an implementation of the JMS specification. The provider can be a JMS implementation of the Java platform, or a message-oriented middleware adapter for a non-Java platform. JMS client: Produce or consume message-based Java applications or objects (that is, producers and consumers are collectively referred to as JMS clients). JMS producer: A JMS client who creates and sends messages. JMS consumer: The JMS client that receives the message. JMS message: an object that can transfer data between JMS clients. JMS queue: an area that contains messages that are sent and waiting to be read. If a message is read, it will be removed from the queue. JMS topic: A mechanism that supports sending messages to multiple subscribers.

2.3 Java Message Service Model

  • Point-to-point model Under the point-to-point queue model, a producer publishes messages to a specific queue, and a consumer reads messages from the queue. Here, the producer knows the consumer's queue and sends the message directly to the consumer's queue. This mode has the following characteristics: Only one consumer will get the message; the producer does not need the consumer to be in the running state during the consumption of the message, and the consumer also does not need to be in the running state when the producer is sending the message; every success All processed messages are signed by the consumer.

  • The publisher/subscriber model The publisher/subscriber model supports publishing messages to a specific message topic. In this model, publishers and subscribers do not know each other, similar to an anonymous bulletin board. This model has the following characteristics: Multiple consumers can obtain messages; There is a time dependence between publishers and subscribers. Publishers need to create a subscription (subscription) so that consumers can subscribe. Subscribers must maintain a continuous active state to receive messages, unless the subscriber establishes a durable subscription.

2.4 Message Queue (ActiveMQ)

ActiveMQ is an implementation of the JMS specification, the following is how to use

  • Download ActiveMQ and go to the official website to download: http://activemq.apache.org/

  • Run ActiveMQ to decompress apache-activemq-5.5.1-bin.zip (similar to Tomcat, it can be used after decompression). Some people I searched on the Internet modified the connection address and protocol in the configuration file activeMQ.xml. I was testing The test can be successful without modification. If your test is unsuccessful, you can modify it as follows:

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

The test code is as follows: Producer Product:

 

public class Product {  private String username = ActiveMQConnectionFactory.DEFAULT_USER;  private String password = ActiveMQConnectionFactory.DEFAULT_PASSWORD;  private String url = ActiveMQConnectionFactory.DEFAULT_BROKER_URL;  private Connection connection = null;  private Session session = null;  private String subject = "myQueue";  private Destination destination = null;  private MessageProducer producer = null;

 /** * @Description 初始化方法 * @Author 刘俊重 * @Date 2017/12/20 */  private void init() throws JMSException {   ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(username, password, url);   connection = connectionFactory.createConnection();   session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);   destination = session.createQueue(subject);   producer = session.createProducer(destination);   producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);  }

 public void productMessage(String message) throws JMSException {this.init(); TextMessage textMessage = session.createTextMessage(message); connection.start(); System.out.println("The producer is ready to send a message:" + textMessage); producer.send(textMessage); System.out.println("The producer has sent the message...");}

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

Consumer:

 

public class Consumer implements MessageListener, ExceptionListener {  private String name = ActiveMQConnectionFactory.DEFAULT_USER;  private String password = ActiveMQConnectionFactory.DEFAULT_PASSWORD;  private String url = ActiveMQConnectionFactory.DEFAULT_BROKER_URL;  private ActiveMQConnectionFactory connectionFactory = null;  private Connection connection = null;  private Session session = null;  private String subject = "myQueue";  private Destination destination = null;  private MessageConsumer consumer = null;  public static Boolean isconnection = false;

 /** * @Description 连接ActiveMQ * @Author 刘俊重 * @Date 2017/12/20 */  private void init() throws JMSException {   connectionFactory = new ActiveMQConnectionFactory(name, password, url);   connection = connectionFactory.createConnection();   session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);   destination = session.createQueue(subject);   consumer = session.createConsumer(destination);  }

 public void consumerMessage() throws JMSException {this.init(); connection.start(); // Set up message monitoring and exception monitoring consumer.setMessageListener(this); connection.setExceptionListener(this); System.out.println("consumption The person starts listening..."); isconnection = true; // Message receive = consumer.receive();}

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

 /** * Exception handling function*/ @Override public void onException(JMSException exception) {// The connection is closed due to an exception isconnection = false;}

 /** * Message processing function*/ @Override public void onMessage(Message message) {try {if (message instanceof TextMessage) {TextMessage textMsg = (TextMessage) message; String text = textMsg.getText(); System.out.println ("The message received by the consumer =======" + text);} else {System.out.println("The received message does not meet");}} catch (JMSException e) {e.printStackTrace( );}}}

Note: Consumers need to implement MessageListener and ExceptionListener to monitor the handling of messages and errors. Producer test class TestProduct:

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

TestProduct is used to simulate the generation of 100 messages and write them to the ActiveMQ queue. Consumer test class TestConsumer:

 

public class TestConsumer implements Runnable {  static Thread thread = null;

 public static void main(String[] args) throws InterruptedException {thread = new Thread(new TestConsumer()); thread.start(); while (true) {// Listen to the message queue at all times, and if the thread dies, create a new one Thread boolean alive = thread.isAlive(); System.out.println("Current thread status:" + alive); if (!alive) {thread = new Thread(new TestConsumer()); thread.start(); System .out.println("Thread restart complete");} 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 uses multiple threads here to ensure that there is a thread alive waiting to receive the ActiveMQ message queue and call the consumer for processing.

Summary: My understanding is that inter-thread communication uses queue, such as BlockingQueue, and inter-process communication uses JMS, such as ActiveMQ.

Attached is an article about message queues written by 58 architect Shen Jian, which can be used as a reference: http://dwz.cn/78yLxL

What needs to be emphasized is that the quotation of any technology must serve to solve business problems, not just show off skills. For example, take messaging services. For example, a user registers for a certain website. After registration, I need to call the email and SMS service to send him a notification. I may also use the information he filled in to recommend someone he might know. Users, then the core business here is registration, other notification and recommendation users can be processed in the message queue, first respond to the registration information, and then call other services to handle the two services of notification and recommendation users. However, the number of users in the early stage of the website may be relatively small, and my needs can be met without message queues. Using message queues will increase the complexity of the project. Therefore, the use of new technologies must solve business problems, rather than simply show off skills. . Reference document: http://blog.csdn.net/fanzhigang0/article/details/43764121http://blog.csdn.net/u010702229/article/details/18085263

Guess you like

Origin blog.csdn.net/keepfriend/article/details/113859444