【问题标题】:Keep JMS consumer alive for messages让 JMS 消费者保持活动状态以获取消息
【发布时间】:2020-09-21 15:06:15
【问题描述】:

我正在编写一个简单的 java 程序来创建一个 JMSConsumer。我希望消费者等到生产者发布一些东西,然后主程序终止。这是我的主要内容:

    JMSContext context;
    Destination destination; 
    JMSConsumer consumer;
    
    JmsConnectionFactory connectionFactory = createJMSConnectionFactory();

    setJMSProperties(connectionFactory);

    System.out.println("MQ Test: Connecting to " + HOST + ", Port " + PORT + ", Channel " + CHANNEL
    + ", Connecting to " + QUEUE_NAME);

    try {
        context = connectionFactory.createContext(); 
        destination = context.createQueue("queue:///" + QUEUE_NAME); 
        consumer = context.createConsumer(destination); 

        MessageListener ml = new DemoMessageListener(); 
        consumer.setMessageListener(ml); 
        
        System.out.println("The message listener is running."); // (Because the connection is started by default)

        context.start();
        
        
    } catch (Exception e){}

问题是当程序到达main的底部时,程序就结束了。
我试图获得的结果类似于 RabbitMq 的 basicConsuime(下面的示例):

public static void main(String[] argv) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();

channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
String queueName = channel.queueDeclare().getQueue();
channel.queueBind(queueName, EXCHANGE_NAME, "");

System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

DeliverCallback deliverCallback = (consumerTag, delivery) -> {
    String message = new String(delivery.getBody(), "UTF-8");
    System.out.println(" [x] Received '" + message + "'");
};
channel.basicConsume(queueName, true, deliverCallback, consumerTag -> { });
}

当main结束时,读取消息的线程还活着,每次向队列发送消息时都会调用deliverCallback。


有什么想法吗?

【问题讨论】:

  • 您实际上想在这里实现什么?如果您的程序只有一个线程,则根本不需要使用MessageListener——只需在循环中调用receive() 即可获取每条消息。或者只是在main() 的末尾加上一个长的Thread.sleep()。很难知道该建议什么,因为我不知道您希望程序如何运行。

标签: java jms


【解决方案1】:

在当前情况下,一旦主进程结束,所有与进程关联的线程都会终止。

有几个选项可以实现您提到的目标。

  1. 您将代码部署在任何容器中,例如 tomcat 作为应用程序 这将保持进程运行。
  2. 其他方法是让您的主线程忙于等待,并在需要时使用 thread.notify 终止。

【讨论】:

  • 当然,你可以做任何这些事情——但应用程序需要那种复杂性吗?如果它所要做的只是获取消息并同步处理它们,它可以重复调用recieve()。更复杂的需求需要更复杂的解决方案;)
【解决方案2】:

好吧,如果您只想做与您的“基本消费”相同的事情,您可以这样做(忘记您的演示侦听器等):

  ...
  try {
    context = connectionFactory.createContext(); 
    destination = context.createQueue("queue:///" + QUEUE_NAME); 
    consumer = context.createConsumer(destination); 

    /*
    MessageListener ml = new DemoMessageListener(); 
    consumer.setMessageListener(ml); 
    
    System.out.println("The message listener is running."); // (Because the connection is started by default)

    context.start();
    */
    
    String  body = consumer.receiveBody(String.class);
    System.out.println("Received message body: " + body);
    
} catch (Exception e){}

【讨论】:

  • 这段代码只有在队列中已经有消息的情况下才有效。我想你不明白我的问题:问题不是从队列中读取消息,问题是找到一个让接收者保持活动状态(也在主程序结束时)监听队列的方法。 “基本消费”示例正是实现了这种场景:同样,当 main 结束时,如果将新消息添加到队列中,则调用 DeliverCallback。
  • 啊,好吧,那么无限循环对你有用吗?获取您的原始代码并添加: while(true) { Thread.sleep(1000); }
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-21
  • 2018-08-23
  • 1970-01-01
  • 2013-08-08
  • 1970-01-01
  • 2015-07-16
相关资源
最近更新 更多