Topic的特点:
- 生产者将消息发布到Topic中,每个消息可以有多个消费者,属于一对多的关系。
- 生产者和消费者存在时间上的相关性。订阅某一主题的消费者只能消费自它订阅只后发布的消息。
- 生产者生产时,topic是不保存消息的,它是无状态的,不落地的,假如无人订阅,那么生产出来的消息就是一条废消息,所以,一般情况下,需要先启动消费者,再启动生产者。
上述内容可以联系微信里的关注公众号来理解,我关注了公众号之后,公众号会给我推送消息,我没有关注,自然不会收到微信公众号发来的消息,并且,这个推送是自我关注之后,才收到的,之前微信公众号发布过的消息,不会给我补发和补推送。
代码和前面的Queue非常类似,直接贴出来了。
package com.wsy.activemq.queue;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class JmsProducer_Topic {
public static final String ACTIVEMQ_URL = "tcp://192.168.0.101:61616";
public static final String TOPIC_NAME = "topic01";
public static void main(String[] args) throws JMSException {
// 创建连接工厂,按照给定的url地址采用默认的用户名和密码
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
// 通过连接工厂,获取Connection并启动
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
// 创建Session
// 有两个参数,第一个是事务,第二个是签收,后面详细介绍
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建目的地(目的地有两个子接口,分别是Queue和Topic)
Topic topic = session.createTopic(TOPIC_NAME);
// 创建消息生产者,生产的消息放到topic中
MessageProducer messageProducer = session.createProducer(topic);
// 使用messageProducer生产消息发送到主题中
for (int i = 0; i < 3; i++) {
// 创建一条消息,可以理解成字符串
TextMessage textMessage = session.createTextMessage("message-" + i);
// 通过messageProducer发送消息给mq
messageProducer.send(textMessage);
}
// 按照资源打开的相反顺序关闭资源
messageProducer.close();
session.close();
connection.close();
}
}
package com.wsy.activemq.queue;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class JmsConsumer_Topic {
public static final String ACTIVEMQ_URL = "tcp://192.168.0.101:61616";
public static final String TOPIC_NAME = "topic01";
public static void main(String[] args) throws JMSException {
// 创建连接工厂,按照给定的url地址采用默认的用户名和密码
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
// 通过连接工厂,获取Connection并启动
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
// 创建Session
// 有两个参数,第一个是事务,第二个是签收,后面详细介绍
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建目的地(目的地有两个子接口,分别是Queue和Topic)
Topic topic = session.createTopic(TOPIC_NAME);
// 创建消费者,指明从topic取消息
MessageConsumer messageConsumer = session.createConsumer(topic);
while (true) {
// 因为向主题中存放的是TextMessage的实例,所以取出来的时候,也要用TextMessage的实例来接收
// 这里的receive()方法表示一直等待,如果给它传一个long类型的毫秒数,表示consumer等待超时时间
TextMessage textMessage = (TextMessage) messageConsumer.receive();
if (textMessage != null) {
System.out.println("消费者消费:" + textMessage.getText());
} else {
break;
}
}
// 按照资源打开的相反顺序关闭资源
messageConsumer.close();
session.close();
connection.close();
}
}
按照前面说的,先启动消费者,后启动订阅者的流程,假设这里启动了三个消费者,启动一个生产者,可以发现,每个消费者都获得了生产者生产的所有消息。
在ActiveMQ的管理界面,可以看到topic01后面有3个订阅者。
表头的英文分别是:主题名称,消费者数量,进入主题的消息数量,离开主题的消息数量,操作。