MQ的思想其实和连接池差不多,只不过一个是队列,一个是多线程。设计模式和原理都类似,ActiveMQ(以下简称amq)实际上是封装了JMS,所以可以在amq里直接使用很多JMS的对象。
去官网去下载 关于amq的安装 so easy 我就不多说了 网上一搜一堆 需要注意的是下载的时候可能会有各种404问题 官网提供了很多的下载URL 国内的网络河蟹 很难下载 你可以换一个其他版本试试 (我就是这样的)
JMS里分为生产者(Producer)和消费者(Consumer)
生产者向队列add data
消费者向队列poll data
我来简单介绍几个MQ重要的对象
ActiveMQConnectionFactory : 实现了jms的ConnectionFactory,Connection的工厂类
Connection :JMS连接,和Java连接池的Connection差不多 Producer和Consumer用来和Broker通讯的
Session : 会话
Destination :目的地,数据要发送到哪里或者从哪里取
MessageProducer: 生产者
MessageConsumer :消费者
Message : 消息,add到队列的东西,也就是自己要处理的东西,Message有很多子接口,TextMessage或ByteMessage神马的 自己根据自己的业务选择接口
以上除了ActiveMQConnectionFactory 是amq的类(实现JMS) 其他的基本都是JMS自己的接口 所以我们在代码里直接使用的接口 因为除了ActiveMQConnectionFactory需要我们创建 其他的对象都不需要我们手动去创建
Producer
ConnectionFactory factory; //连接工厂
Connection connection;//jms连接
Session session;//发送、接收线程
Destination destination;//消息目的地
MessageProducer producer;//消息发送者
factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD,
"tcp://localhost:61616"); //获取工厂实例
/**
* 以上步骤可使用单例模式等方法,让ActiveMQConnectionFactory始终只创建一次(和SessionFactory的性质差不多)
*/
try {
connection = factory.createConnection(); //获取Connection
connection.start(); //打开Connection
session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE); //创建Session并选择事务和ACK模式
destination = session.createQueue("rdp_import_queue"); //根据自己的队列名称创建Destination(如果没有队列,MQ会自己创建队列)
producer = session.createProducer(destination); //创建生产者
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); //是否为持久化 ,NON_PERSISTENT非持久化 ,PERSISTENT持久化
for (int i = 1; i < 13; i++) {
String msg = "第" + i + "次发送消息";
TextMessage textMessage = session.createTextMessage(msg);
producer.send(textMessage);
}
//关闭对象
producer.close();
session.commit();
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
Consumer 下面就不写注释了 和上面一样
connection = factory.createConnection();
connection.start();
session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
destination = session.createQueue("rdp_import_queue");
consumer = session.createConsumer(destination); // 创建Consumer
while (true) {
TextMessage textMessage = (TextMessage) consumer.receive(); // 接收Message
if (textMessage != null && !textMessage.getJMSRedelivered()) { //检查是否已经接收过
System.out.println(textMessage.getText());
textMessage.acknowledge(); //通知已接收
}
Thread.sleep(1000);
}
有几个地方要注意一下
1、ConnectionFactory的生命周期 此对象不要频繁创建 全局创建一个就好 每次用该对象获取Connection就好了
1、DeliveryMode 持久化方式,开发中可以选择对Message是否要做持久化,持久化的Message在重启amq后还会依然存在,非持久化会自动被干掉(但是会临时存放于amp),
其值为NON_PERSISTENT非持久化 ,PERSISTENT持久化
2、ACK(Acknowledgement),先说下什么是ACK,ACK即确认字符,在数据通信中,接收站发给发送站的一种传输类控制字符。表示发来的数据已确认接受无误。ACK信号通常是一个ASCII字符,不同的协议中ACK信号都不一样。
当Consumer拿到Message之后要通知Broker已确认接收,否则其他Consumer会认为该Message依然可用,JMS的Session中提供了四种ACK_MODE
AUTO_ACKNOWLEDGE = 1 自动确认
CLIENT_ACKNOWLEDGE = 2 客户端手动确认
DUPS_OK_ACKNOWLEDGE = 3 自动批量确认
SESSION_TRANSACTED = 0 事务提交并确认
AcitveMQ对此补充了一个自定义的ACK_MODE: INDIVIDUAL_ACKNOWLEDGE = 4 单条消息确认