消息队列一般有两种模型
1.点对点模型(基于队列 Point to Point,PTP) 每个消息只能有一个消费者。消息的生产者和消费者之间没有时间上的 相关性.可以有多个发送者,但只能被一个消费者消费。 一个消息只能被一个接受者接受一次 生产者把消息发送到队列中(Queue),接受者无需订阅,当接受者未接受到消息时就会处于阻塞状态
2. 发布者/订阅者模型(基于主题的Publish/Subscribe,pub/sub) 每个消息可以有多个消费者。 生产者和消费者之间有时间上的相关性。订阅一个主题的消费者只能消 费自它订阅之后发布的消息. 允许多个接受者,类似于广播的方式 生产者将消息发送到主题上(Topic) 接受者必须先订阅 注:持久化订阅者:特殊的消费者,告诉主题,我一直订阅着,即使网络断开,消息服务器也记住所有持久化订阅者,如果有新消息,也会知道必定有人回来消费。
点对点模式
发送者:
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
public class Sender {
public static void main(String[] args) throws JMSException, InterruptedException {
// 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: 一个发送或接收消息的线程
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
// Destination :消息的目的地;消息发送给谁.
Destination destination = session.createQueue("my-queue");
// MessageProducer:消息发送者
MessageProducer producer = session.createProducer(destination);
// 设置不持久化,可以更改
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
for(int i=0;i<20;i++){
//创建文本消息
TextMessage message = session.createTextMessage("hello 我是消息:"+i);
Thread.sleep(1000);
//发送消息
producer.send(message);
}
session.commit();
session.close();
connection.close();
}
}
消费者:
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
public class Receiver {
// ConnectionFactory :连接工厂,JMS 用它创建连接
private static ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER,
ActiveMQConnection.DEFAULT_PASSWORD, InitParams.url);
public static void main(String[] args) throws JMSException {
// Connection :JMS 客户端到JMS Provider 的连接
final Connection connection = connectionFactory.createConnection();
connection.start();
// Session: 一个发送或接收消息的线程
final Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
// Destination :消息的目的地;消息送谁那获取.
Destination destination = session.createQueue("my-queue");
// 消费者,消息接收者
MessageConsumer consumer1 = session.createConsumer(destination);
System.out.println("===========consumer1开始监听消息=========");
consumer1.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message msg) {
try {
TextMessage message = (TextMessage)msg ;
System.out.println("consumer1收到消息: "+message.getText());
session.commit();
} catch (JMSException e) {
e.printStackTrace();
}
}
});
// 再来一个消费者,消息接收者
MessageConsumer consumer2 = session.createConsumer(destination);
System.out.println("===========consumer2开始监听消息=========");
consumer2.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message msg) {
try {
TextMessage message = (TextMessage)msg ;
System.out.println("consumer2收到消息: "+message.getText());
session.commit();
} catch (JMSException e) {
e.printStackTrace();
}
}
});
}
}
首先运行Sender,登录mq后台
可以看到 my-queue这个队列里阻塞了20条消息,0个消费者。
再运行Receiver
查看后台:
可以看到有两个消费者,20条消息也已经消费完毕了。从打印的日志也可以看出,点对点模式并不是只能有一个消费者,而是一条消息只能有一个消费者消费。