由于在实际应用中,简单队列模型无法解决很多实际问题,而且生产者和消费者是一对一的关系。模型较为单一。故引入Work模式。

这里写图片描述

  1. 一个生产者、多个消费者。
  2. 一个消息只能被一个消费者获取。

测试实现: 
1、生产者

  1. private final static String QUEUE_NAME = "test_queue_work";
  2. public static void main(String[] argv) throws Exception {
  3. // 获取到连接以及mq通道
  4. Connection connection = ConnectionUtil.getConnection();
  5. Channel channel = connection.createChannel();
  6. // 声明队列
  7. channel.queueDeclare(QUEUE_NAME, false, false, false, null);
  8. for (int i = 0; i < 50; i++) {
  9. // 消息内容
  10. String message = "" + i;
  11. channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
  12. System.out.println(" [x] Sent \'" + message + "\'");
  13. Thread.sleep(i * 10);
  14. }
  15. channel.close();
  16. connection.close();
  17. }

生产者循环创建消息 
2、消费者一

  1. private final static String QUEUE_NAME = "test_queue_work";
  2. public static void main(String[] argv) throws Exception {
  3. // 获取到连接以及mq通道
  4. Connection connection = ConnectionUtil.getConnection();
  5. Channel channel = connection.createChannel();
  6. // 声明队列
  7. channel.queueDeclare(QUEUE_NAME, false, false, false, null);
  8. // 同一时刻服务器只会发一条消息给消费者
  9. channel.basicQos(1);
  10. // 定义队列的消费者
  11. QueueingConsumer consumer = new QueueingConsumer(channel);
  12. // 监听队列,手动返回完成
  13. channel.basicConsume(QUEUE_NAME, false, consumer);
  14. // 获取消息
  15. while (true) {
  16. QueueingConsumer.Delivery delivery = consumer.nextDelivery();
  17. String message = new String(delivery.getBody());
  18. System.out.println(" [x] Received \'" + message + "\'");
  19. //休眠
  20. Thread.sleep(10);
  21. // 返回确认状态
  22. channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
  23. }
  24. }

3、消费者二 
注意:channel.basicQos(1); 被注释掉了

  1. private final static String QUEUE_NAME = "test_queue_work";
  2. public static void main(String[] argv) throws Exception {
  3. // 获取到连接以及mq通道
  4. Connection connection = ConnectionUtil.getConnection();
  5. Channel channel = connection.createChannel();
  6. // 声明队列
  7. channel.queueDeclare(QUEUE_NAME, false, false, false, null);
  8. // 同一时刻服务器只会发一条消息给消费者
  9. // channel.basicQos(1);
  10. // 定义队列的消费者
  11. QueueingConsumer consumer = new QueueingConsumer(channel);
  12. // 监听队列,手动返回完成状态
  13. channel.basicConsume(QUEUE_NAME, false, consumer);
  14. // 获取消息
  15. while (true) {
  16. QueueingConsumer.Delivery delivery = consumer.nextDelivery();
  17. String message = new String(delivery.getBody());
  18. System.out.println(" [x] Received \'" + message + "\'");
  19. // 休眠1秒
  20. Thread.sleep(1000);
  21. channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
  22. }
  23. }

1、 消费者1和消费者2获取到的消息内容是不同的,同一个消息只能被一个消费者获取。 
2、 消费者1和消费者2获取到的消息的数量是相同的,一个是奇数一个是偶数。

其实,这样是不合理的,应该是消费者1要比消费者2获取到的消息多才对。

消费者从队列中获取消息,服务端如何知道消息已经被消费呢?

模式1:自动确认

  1. 只要消息从队列中获取,无论消费者获取到消息后是否成功消息,都认为是消息已经成功消费。

模式2:手动确认

  1. 消费者从队列中获取消息后,服务器会将该消息标记为不可用状态,等待消费者的反馈,如果消费者一直没有反馈,那么该消息将一直处于不可用状态。

  1. 集群中同时监听一个服务队列

 

版权声明:本文为shanheyongmu原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/shanheyongmu/p/10406155.html