ActionMQ的P2P模式 同步与异步验证
依赖包:activemq-all-5.15.3.jar,activemq-broker-5.15.3.jar,activemq-client-5.15.3.jar,geronimo-j2ee-
management_1.1_spec-1.0.1.jar,geronimo-jms_1.1_spec-1.1.1.jar,slf4j-api-1.7.25.jar
(1)同步
订阅者或接收者通过receive方法来接收消息,receive方法在接收到消息之前(或超时之前)将一直阻塞;
(2)异步
订阅者或接收者可以注册为一个消息监听器。当消息到达之后,系统自动调用监听器的onMessage方法。
何为消息队列的同步和异步?
这里明确声明下 不要和前端ajax的同步异步 和多线程的同步和异步搞混啦
同步,异步:原理和多线成同步,异步原理机制一样 不同点 使用环境
者发来的数据,不能做其他的业务。且完成接受并处理完生产者发来的数据 才可以接受下一个生产者的数据!
但在消息队列中,生产者的模式都是异步模式的;比如生产者登录一个网站平台,并注册了账户。他便可以去操做其他事项啦;不用等待接受后端注册成功确认消息后,才可以去操作其他的;(数据量高并发的情况下);
生产者代码:
package demo.actionmq;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
public class Send {
public static void sendProduct(String list) {
try {
// ConnectionFactory :连接工厂,JMS 用它创建连接
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER,
ActiveMQConnection.DEFAULT_PASSWORD, "tcp://localhost:61616");
// Connection :JMS 客户端到JMS Provider 的连接
Connection connection = connectionFactory.createConnection();
connection.start();
// Session: 一个发送或接收消息的线程 false 关闭事物
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// Destination :消息的目的地;消息发送给谁. MyQueue消费者和生产者统一
Destination destination = session.createQueue("MyQueue");
// MessageProducer:消息发送者
MessageProducer producer = session.createProducer(destination);
// 设置不持久化,可以更改 deliveryMode为传送模式,priority为消息优先级,timeToLive为消息过期时间。
//Persistent 持久的 non persistent不持久的
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
// 创建文本消息
TextMessage message = session.createTextMessage(list);
// 发送消息
producer.send(message);
session.close();
connection.close();
} catch (Exception e) {
e.getStackTrace();
System.out.println("连接异常!");
}
}
public static void main(String[] args) throws Exception {
System.out.println("-------生产者-------");
for (int i = 1; i <= 5; i++) {
if (i == 5) {
System.out.println("我是生产者最后" + i + "号!");
Send.sendProduct("我是生产者最后" + i + "号!");
} else {
System.out.println("我是生产者 " + i + "号!");
Send.sendProduct("我是生产者 " + i + "号!");
}
Thread.sleep(1000);
}
System.out.println("-------生产结束发送-------");
}
}
同步消费者代码:
package demo.actionmq;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.springframework.util.StringUtils;
//消息队列同步 recive方法 p2p消费模式
public class Syn_Receiver {
// Connection表示在客户端和JMS系统之间建立的链接(对TCP/IP socket的包装)。
// Connection可以产生一个或多个Session。跟ConnectionFactory一样,
// Connection也有两种类型:QueueConnection(p2p模式 一对一)和TopicConnection(Pub/sub模式 一对多)
private QueueConnection connection = null;
// Session是操作消息的接口。可以通过session创建生产者、消费者、消息等。Session提供了事务的功能。
// 当需要使用session发送/接收多个消息时,可以将这些发送/接收动作放到一个事务中。
// 同样,也分QueueSession和TopicSession
private Session session = null;
//创建消费者
private MessageConsumer consumer;
//判断是否结束
private Boolean flag=true;
// 初始化消费者连接通信
public void initialize() {
try {
// 获得连接工厂 通信地址默认都是tcp://localhost:61616
// 创建Connection对象的工厂,针对两种不同的jms消息模型,分别有QueueConnectionFactory和TopicConnectionFactory两种。
// 可以通过JNDI来查找ConnectionFactory对象
QueueConnectionFactory connectFactory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER,
ActiveMQConnection.DEFAULT_PASSWORD, "tcp://localhost:61616");
// 客户端和JMS系统之间建立链接
connection = connectFactory.createQueueConnection();
// 创建操作消息的接口 一个发送或接收消息的线程 true 为支持事物 false不支持事物
// 第二参数可以为Session.AUTO_ACKNOWLEDGE:为自动确认,客户端发送和接收消息不需要做额外的工作。
// Session.CLIENT_ACKNOWLEDGE:为客户端确认。客户端接收到消息后,必须调用javax.jms.Message的acknowledge方法。jms服务器才会删除消息。
// DUPS_OK_ACKNOWLEDGE:允许副本的确认模式。一旦接收方应用程序的方法调用从处理消息处返回,会话对象就会确认消息的接收;而且允许重复确认。在需要考虑资源使用时,这种模式非常有效
session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建消息队列 把接收到的信息都发送到Destination
Destination destination = session.createQueue("MyQueue");
// 创建消费者 其中session.createDurableSubscriber为持久化订阅者 session.createTopic创建订阅者
// 创建2个消费者
consumer = session.createConsumer(destination);
connection.start();
} catch (Exception e) {
e.printStackTrace();
System.out.println("同步初始化失败");
}
}
// alis别名 用于区分多个消费者 同步使程序处于堵塞中
public void recive(String alis) {
try {
initialize();
System.out.println("-----同步阻塞中-----");
System.out.println("--------------我是:" + alis + "为你服务-----------");
while(flag) {
Message message = consumer.receive(); // 主动接收消息(同步)
if(null != message) {
String result=((TextMessage) message).getText();
System.out.println(alis + "接受消息:" + result);
if(StringUtils.hasText(result))
if(result.contains("最后"))flag=false;
}
}
//结束连接
close();
} catch (JMSException e) {
e.printStackTrace();
}
}
// 事物提交 用于开启了事物的
public void submit() throws JMSException {
session.commit();
}
// 关闭连接
public void close() throws JMSException {
System.out.println("Consumer:->Closing connection");
if (consumer != null)
consumer.close();
if (session != null)
session.close();
if (connection != null)
connection.close();
System.out.println("-----同步结束-----");
//System.exit(0);
}
}
测试同步代码块: 先启动消费者 使其处于接受状态
package demo.actionmq;
import javax.jms.Destination;
import javax.jms.MessageConsumer;
import javax.jms.Session;
public class p2pTest {
public static void main(String[] args) throws Exception {
// 同步
syn();
System.out.println("-------系统堵塞中 我不能做其他业务-------");
}
// 同步块测试 p2p模式
public static void syn() {
// 同步消费
try {
// 同步消费
Syn_Receiver sr = new Syn_Receiver();
sr.recive("消费一号");
} catch (Exception e) {
e.printStackTrace();
}
}
}
异步代码块:先启动消费者 使其处于接受状态
package demo.actionmq;
import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
//消息队列异步 MessageListener p2p消费模式
public class Asy_Receiver{
// Connection表示在客户端和JMS系统之间建立的链接(对TCP/IP socket的包装)。
// Connection可以产生一个或多个Session。跟ConnectionFactory一样,
// Connection也有两种类型:QueueConnection(p2p模式 一对一)和TopicConnection(Pub/sub模式 一对多)
private Connection connection = null;
// Session是操作消息的接口。可以通过session创建生产者、消费者、消息等。Session提供了事务的功能。
// 当需要使用session发送/接收多个消息时,可以将这些发送/接收动作放到一个事务中。
// 同样,也分QueueSession和TopicSession
private Session session = null;
// 获取队列消息
private TextMessage txtMsg = null;
// 初始化消费者连接通信
public Session getSession() {
try {
// 获得连接工厂 通信地址默认都是tcp://localhost:61616
// 创建Connection对象的工厂,针对两种不同的jms消息模型,分别有QueueConnectionFactory和TopicConnectionFactory两种。
// 可以通过JNDI来查找ConnectionFactory对象
QueueConnectionFactory connectFactory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER,
ActiveMQConnection.DEFAULT_PASSWORD, "tcp://localhost:61616");
// 客户端和JMS系统之间建立链接
QueueConnection connection = connectFactory.createQueueConnection();
// 创建操作消息的接口 一个发送或接收消息的线程 true 为支持事物 false不支持事物
// 第二参数可以为Session.AUTO_ACKNOWLEDGE:为自动确认,客户端发送和接收消息不需要做额外的工作。
// Session.CLIENT_ACKNOWLEDGE:为客户端确认。客户端接收到消息后,必须调用javax.jms.Message的acknowledge方法。jms服务器才会删除消息。
// DUPS_OK_ACKNOWLEDGE:允许副本的确认模式。一旦接收方应用程序的方法调用从处理消息处返回,会话对象就会确认消息的接收;而且允许重复确认。在需要考虑资源使用时,这种模式非常有效
session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
// 开启连接
connection.start();
return session;
} catch (Exception e) {
e.printStackTrace();
System.out.println("异步初始化失败");
}
return null;
}
// alis别名 用于区分多个消费者
public void recive(MessageConsumer consumer, String alis) {
try {
System.out.println("-----异步中监听着-----");
System.out.println("--------------我是:" + alis + "为你服务-----------");
// 开始监听
consumer.setMessageListener(new MessageListener() {
//监听接受消息
@Override
public void onMessage(Message arg0) {
try {
if (arg0 instanceof TextMessage) {
txtMsg = (TextMessage) arg0;
System.out.println(alis+"接受消息:"+txtMsg.getText());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}); // (异步接收)
} catch (JMSException e) {
e.printStackTrace();
}
}
// 事物提交 用于开启了事物的
public void submit() throws JMSException {
session.commit();
}
// 关闭连接
public void close(MessageConsumer one,MessageConsumer two,Session session) throws JMSException {
System.out.println("Consumer:->Closing connection");
if (one != null)
one.close();
if (two != null)
two.close();
if (session != null)
session.close();
if (connection != null)
connection.close();
System.out.println("-----异步结束-----");
}
}
异步测试:
package demo.actionmq;
import javax.jms.Destination;
import javax.jms.MessageConsumer;
import javax.jms.Session;
public class p2pTest2 {
public static void main(String[] args) throws Exception {
// 异步
asy();
System.out.println("-------在监听着 我去做其他的业务-------");
}
// 异步块测试 p2p模式
public static void asy() {
try {
// 同步消费
Asy_Receiver ar = new Asy_Receiver();
Session session = ar.getSession();
// 创建消息队列 把接收到的信息都发送到Destination
Destination destination = session.createQueue("MyQueue");
// 创建消费者 其中session.createDurableSubscriber为持久化订阅者 session.createTopic创建订阅者
// 创建2个消费者
MessageConsumer one = session.createConsumer(destination);
MessageConsumer two = session.createConsumer(destination);
ar.recive(one, "消费一号");
ar.recive(two, "消费二号");
ar.close(one,two,session);
} catch (Exception e) {
e.printStackTrace();
}
}
}