3

我有一个正在接收一些 TextMessages 的消息侦听器。当它收到一个 ObjectMessage 时,我希望它停止监听队列。我的问题是,当我在 onMessage(Message msg) 方法中调用 consumer.close() 时,ObjectMessage 似乎没有从队列中删除。如果我在 onMessage() 方法之后使用一些标记来告诉 consuemr 关闭,则侦听器可能会在它实际关闭之前使用另一条消息。有什么建议么?这是一些代码。Session、Connection 和 InitialContext 尚未关闭。

public class MyListener implements MessageListener{
    MessageConsumer consumer;

    public MyListener(MessageConsumer mc){
        consumer = mc;
    }

    @Override
    public void onMessage(Message msg) {
        try{
            if(msg instanceof ObjectMessage){
                consumer.close();
            }
            if (msg instanceof TextMessage){
                TextMessage tmsg = (TextMessage) msg;
                String xml = tmsg.getText();
                // do some stuff                
            }

       }catch(Exception e){
           e.printStackTrace();
       }
    }
4

5 回答 5

5

不要使用异步MessageListener.

而是receive在循环中的主线程中使用正常的同步方法。如果您收到您的特殊消息,您可以确认并从循环中中断以关闭会话并终止程序。

于 2013-09-13T16:46:40.347 回答
2

根据JMS 规范connection.stop(),您不能调用or connection.close()from是正确的,但是您可以从其他线程调用and ,所以在我的情况下,我只是在需要停止连接时设置 volatile 变量,并在其他线程中检查我可以调用并且不会出现异常或死锁。onMessage()connection.close()connection.stop()onMessage()connection.stop()connection.close()

> 从 JMS 2.0 规范:

6.1.5。暂停传入消息的传递 如果调用 stop 时任何消息侦听器正在运行,stop 必须等到所有消息侦听器都返回后才能返回。当这些消息侦听器完成时,它们必须拥有可用的连接的全部服务。消息侦听器不得尝试停止自己的连接,因为这会导致死锁。JMS 提供者必须检测到这一点并抛出 javax.jms.IllegalStateException。

> 从 JMS 1.1 开始:

4.3.4 暂停传递传入消息 如果调用stop 时MessageListeners 正在运行,stop 必须等到它们都返回后才能返回。当这些 MessageListener 完成时,它们必须拥有可用的连接的全部服务。

于 2018-02-01T14:17:44.937 回答
0

在尝试解决这个问题几个小时后,我想我找到了一种停止异步消息使用者(MessageListener)的方法。该解决方案涉及使用 Java 锁(同步语句和等待/通知方法)。

首先,在您的主线程上,您需要在启动 JMS 连接后锁定消息侦听器并调用消息侦听器“等待”方法。在您的消息侦听器上,您需要再次锁定消息侦听器,然后调用“全部通知”方法。

  // Main thread ...
  public static void main(String[] args) {
    // ...
    try {
      Connection jmsConn;
      MessageConsumer msgConsumer;
      MessageListener msgListener;
      // ...
      msgConsumer.setMessageListener(msgListener);
      // ...
      synchronized (msgListener) {
        jmsConn.start();
        msgListener.wait();
      }
      jmsConn.stop();
      //...
    } catch (Exception e) {
      // ...
    }
  }


  // MessageListener onMessage...
  public void onMessage(Message jmsMsg) {
    try {
      // ...
      synchronized (this) {
        this.notifyAll();
      }
    } catch (Exception e) {
      // ...
    }
  }

米格尔·亚伯拉罕

于 2015-04-30T00:09:35.313 回答
0

首先阅读文档。您可能有另一个线程正在访问MessageConsumer,并且调用的线程close()将阻塞,直到其他线程完成。

于 2013-09-13T14:17:11.517 回答
-1

这可能有点老了,但是由于我遇到了同样的问题并遇到了它,所以我想我会发布我的发现来帮助其他人。

我遇到了与问题相同的问题,我创建了一个设置异步侦听器的 JMS 接收器类;

TopicSubscriber receiver = myTopicSession.createSubscriber(myTopic);  
JmsMessageListener listener = new JmsMessageListener();
receiver.setMessageListener(listener);

然后我无法以一种好的方式终止侦听器。

我发现解决方案实际上是关闭与我的主题的连接。这也将终止侦听器线程。

myTopicConnection.close();

这意味着在我的主线程中,我必须保持与我创建的 JMS 接收器类的链接,然后调用 close() 方法将其关闭。

于 2015-06-11T10:01:56.690 回答