在我们实际的开发中可能存在这么一种情况,应用程序要向一个队列名为queue的队列中发送3条消息,需要保证这3条消息按顺序消费。必须是第一条消费完,在消费第二条然后是第三条。而我们的程序中可能有时候存在多个consumer对这个队列进行消费,那么可能出现消息时按1,2,3进行消费的,但第二条可能比较耗时,就会导致第2条消息没有消费完,第三条消息就已经消费完了,这个时候可能就会出现问题。

解决方案:1、使用独有消费者就可以解决这个问题。(在创建队列的时候,向队列后面增加参数 ?consumer.exclusive=true

2、使用消息分组也可以进行解决(比上面一种方案好)

3、本博文使用的是独有消费者进行解决

场景模拟:向队列中发送3条消费,且在消费第二条消费时,线程沉睡5秒中,程序中启动2个监听对消息进行消费,看消息的消费结果

队列是属于点对点的模式,且队列中的一条消费只可能被一个消费者进行消费

1、pom文件的配置

<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.11.1</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
<version>5.12.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>4.3.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>4.3.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>4.3.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.8.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-pool</groupId>
<artifactId>commons-pool</artifactId>
<version>1.6</version>
</dependency>

2、消息监听器一 (消费者一)

public class ExclusiveConsumerListener implements SessionAwareMessageListener<TextMessage> {
@Override
public void onMessage(TextMessage message, Session session) throws JMSException {
String msg = message.getText();
if (msg.startsWith("2")) {
try {
System.out.println(Thread.currentThread().getName() + " 开始沉睡5秒.");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " : " + this.getClass().getName() + " :开始消费消息:" + msg);
}
}

3、消息监听器二(消费者二)

public class ExclusiveConsumerListener2 implements SessionAwareMessageListener<TextMessage> {
@Override
public void onMessage(TextMessage message, Session session) throws JMSException {
String msg = message.getText();
if (msg.startsWith("2")) {
try {
System.out.println(Thread.currentThread().getName() + " 开始沉睡5秒.");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " : " + this.getClass().getName() + " :开始消费消息:" + msg);
}
}

4、配置文件(没有实现消息的独有消费

<bean id="connectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory">
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="alwaysSyncSend" value="true" />
<property name="brokerURL" value="tcp://localhost:61616" />
</bean>
</property>
<property name="maxConnections" value="10" />
</bean> <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory" />
<property name="defaultDestination" ref="queue" />
<property name="pubSubDomain" value="false" />
</bean> <bean id="exclusiveConsumerListener" class="com.huan.activemq.独有消费者.ExclusiveConsumerListener" />
<bean id="exclusiveConsumerListener2" class="com.huan.activemq.独有消费者.ExclusiveConsumerListener2" />
<bean id="queue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg name="name" value="spring-queue" />
</bean>
<jms:listener-container acknowledge="auto"
connection-factory="connectionFactory" container-type="default"
destination-type="queue">
<jms:listener destination="spring-queue" ref="exclusiveConsumerListener" />
<jms:listener destination="spring-queue" ref="exclusiveConsumerListener2" />
</jms:listener-container>

5、测试

public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:application-exclusive-consumer.xml");
JmsTemplate jmsTemplate = ctx.getBean(JmsTemplate.class);
String msg1 = "1-这是第一条消息";
String msg2 = "2-这是第二条消息";
String msg3 = "3-这是第三条消息";
jmsTemplate.convertAndSend(msg1);
jmsTemplate.convertAndSend(msg2);
jmsTemplate.convertAndSend(msg3);
}

6、测试结果(可以看到消息是乱的,并没有按照1消费完后消费2,2消费完后消费3)

7、修改配置文件(在队列的字符串后面加上?consumer.exclusive=true实现消费的独有消费


 8、重新测试(结果为按照顺序消费的

activemq实现队列的独有消费的更多相关文章

  1. ActiveMQ(4)---ActiveMQ原理分析之消息消费

    消费端消费消息的原理 我们通过上一节课的讲解,知道有两种方法可以接收消息,一种是使用同步阻塞的MessageConsumer#receive方法.另一种是使用消息监听器MessageListener. ...

  2. activemq消息队列的使用及应用docker部署常见问题及注意事项

    activemq消息队列的使用及应用docker部署常见问题及注意事项 docker用https://hub.docker.com/r/rmohr/activemq/配置在/data/docker/a ...

  3. JAVA的设计模式之观察者模式----结合ActiveMQ消息队列说明

    1----------------------观察者模式------------------------------ 观察者模式:定义对象间一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的 ...

  4. ActiveMQ消息队列从入门到实践(4)—使用Spring JMS收发消息

    Java消息服务(Java Message Service ,JMS)是一个Java标准,定义了使用消息代理的通用API .在JMS出现之前,每个消息代理都有私有的API,这就使得不同代理之间的消息代 ...

  5. ActiveMQ 消息队列服务

      1 ActiveMQ简介 1.1 ActiveMQ是什么 ActiveMQ是一个消息队列应用服务器(推送服务器).支持JMS规范. 1.1.1 JMS概述 全称:Java Message Serv ...

  6. Dyno-queues 分布式延迟队列 之 生产消费

    Dyno-queues 分布式延迟队列 之 生产消费 目录 Dyno-queues 分布式延迟队列 之 生产消费 0x00 摘要 0x01 前情回顾 1.1 设计目标 1.2 选型思路 0x02 产生 ...

  7. C#实现ActiveMQ消息队列

    本文使用C#实现ActiveMQ消息队列功能. 一.首先需要导入两个包,分别是:Apache.NMS 和 Apache.NMS.ActiveMQ 二.创建Winform程序实现生产者功能. 三.Pro ...

  8. SpringBoot集成ActiveMq消息队列实现即时和延迟处理

    原文链接:https://blog.csdn.net/My_harbor/article/details/81328727 一.安装ActiveMq 具体安装步骤:自己谷歌去 二.新建springbo ...

  9. 基于APM实现RPC服务和消息队列的指定消费

    本文内容是基于公司现有框架整理的一篇专利文章.该框架包含完整的一套DevOps流程,包括工单系统(容器申请.服务部署等)\配置中心\路由配置中心\服务治理平台\消息治理平台\葛朗台(基于Docker+ ...

随机推荐

  1. Identity角色管理四(删除角色)

    角色删除方法 [HttpPost] [ValidateAntiForgeryToken] public async Task<ActionResult> Delete(string id) ...

  2. 自定义-starter

    目录 说明 编写启动器 新建项目测试我们自己写的启动器 分析完毕了源码以及自动装配的过程,可以尝试自定义一个启动器来玩玩! 自动装配的过程 SpringBoot-静态资源加载-源码 SpringBoo ...

  3. 找不到方法:“Void System.Data.Objects.ObjectContextOptions.set_UseConsistentNullReferenceBehavior(Boolean)

    找不到方法:"Void System.Data.Objects.ObjectContextOptions.set_UseConsistentNullReferenceBehavior(Boo ...

  4. AES加密基本原理图解

    AES加密 Fright-Moch整理 AES简介 高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的).对 ...

  5. 多线程run()方法是不能够被直接调用的

    操作系统线程的五种状态: 1.新建状态(New):新创建了一个线程对象. 2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于"可运行 ...

  6. C++课后习题

    一.设计一个类people,有保护数据成员:age(年龄,整型),name(姓名,string),行为成员:两个构造函数(一个默认,另一个带参数):析构函数:void setValue(int m, ...

  7. Django学习day11随堂笔记

    今日考题 """ 今日考题 1.简述自定义分页器的使用 2.forms组件是干什么用的,它的主要功能有哪些功能,你能否具体说说每个功能下都有哪些经常用到的方法及注意事项( ...

  8. javascript 定时器 timer setTimeout setInterval (js for循环如何等待几秒再循环)

    实现一个打点计时器,要求1.从 start 到 end(包含 start 和 end),每隔 100 毫秒 console.log 一个数字,每次数字增幅为 12.返回的对象中需要包含一个 cance ...

  9. 关于ModuleNotFoundError: No module named 'xxx' 模块导入失败问题

    我在执行数据库迁移命令的时候pycharm报错,提示ModuleNotFoundError: No module named 'ckeditor',但是我确实是导进来了,而且这个包也从settings ...

  10. 鸿蒙内核源码分析(内存管理篇) | 虚拟内存全景图是怎样的 | 百篇博客分析OpenHarmony源码 | v12.04

    百篇博客系列篇.本篇为: v12.xx 鸿蒙内核源码分析(内存管理篇) | 虚拟内存全景图是怎样的 | 51.c.h .o 内存管理相关篇为: v11.xx 鸿蒙内核源码分析(内存分配篇) | 内存有 ...