在我们实际的开发中可能存在这么一种情况,应用程序要向一个队列名为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. awk工作流程

    awk 工作过程:先执行BEGIN模块,再跟文本交互,最后执行END模块.也就是说BEGIN/END模块,这俩是单独操作跟文本是同一级,但执行有优先级,BEGIN模块>文本>END模块 行 ...

  2. 学习PHP中好玩的Gmagick图像操作扩展的使用

    在 PHP 的图像处理领域,要说最出名的 GD 库为什么好,那就是因为它不需要额外安装的别的什么图像处理工具,而且是随 PHP 源码一起发布的,只需要在安装 PHP 的时候添加上编译参数就可以了. G ...

  3. Shell系列(38)- 数组操作→取值、遍历、替换、删除

    引言 在Linux平台上工作,我们经常需要使用shell来编写一些有用.有意义的脚本程序.有时,会经常使用shell数组.那么,shell中的数组是怎么表现的呢,又是怎么定义的呢?接下来逐一的进行讲解 ...

  4. ActiveQq的代码实现

    ]从java代码开始再过渡到springboot Java代码的实现 1.activemq这个消息中间件有两种形式 1. p2p(生产者,消费者) 特点: 生产者: package com.lqh; ...

  5. python 语法规范

    在python shell 中输入 import this 可以看到python之禅 The Zen of Python, by Tim Peters Beautiful is better than ...

  6. ci框架驱动器

    1.驱动器什么是 驱动器是一种特殊类型的类库,它有一个父类和任意多个子类.子类可以访问父类, 但不能访问兄弟类.在你的控制器中,驱动器为你的类库提供了 一种优雅的语法,从而不用将它们拆成很多离散的类. ...

  7. nginx 常用教程网址

    nginx rewrite比较齐全的教程 http://www.bubuko.com/infodetail-1810501.html

  8. truncate表时报“唯一/主键被启用的外部关键字引用”解决办法

    前言:清空表时提示"唯一/主键被启用的外部关键字引用"这一警告信息 原因:是因为主键被子表引用,所以对主键进行更改就好了 解决: 使用 alter table table_name ...

  9. 自学 Python,视频教程和代码一看就懂,动手就废,应该这么学

    ​ 一.代码量太少了,看得多做得少,导致一做就错. 每一个测试工程师必定是在大量的时间和代码中提升的自己,如果你只是看视频的话,那永远都停留在理论上,很多问题是要实践才能发现的 我打个比方你看视频的时 ...

  10. 13万字详细分析JDK中Stream的实现原理

    前提 Stream是JDK1.8中首次引入的,距今已经过去了接近8年时间(JDK1.8正式版是2013年底发布的).Stream的引入一方面极大地简化了某些开发场景,另一方面也可能降低了编码的可读性( ...