当消费者关闭时,javax.jms.MessageConsumer会挂起

时间:2011-11-04 09:01:16

标签: java jms ibm-mq

根据javadoc,如果我在javax.jms.MessageConsumer上调用receive(),它将无限期地阻塞,直到产生消息或消息使用者关闭为止。

我有一个调用receive()的线程。作为线程关闭的一部分,我调用close(),但是消费者仍然在receive()中阻塞,因此线程不会关闭。我的代码的要点是:

public String receiveMessage() {
...
...
   System.out.println("About to receive")
   TextMessage message = (TextMessage) consumer.receive();
   System.out.println("No longer receiving")
...
...
}

public void stop() {
    try {
        if (consumer != null) {
            consumer.close();
        }
    } catch (JMSException ex) {
        throw new IllegalStateException(ex);
    }
}

在调试器中,我可以看到正在调用close(),但接收仍然阻塞。如果我使用带有超时的receive()方法,它将一直阻塞,直到超时到期。

一切看起来都对我好,希望有人可以告诉我我做错了什么。

4 个答案:

答案 0 :(得分:5)

我已经对问题进行了排序,我没有在任何地方进行connection.start()。一旦我把它放入,MessageConsumer.receive()在我关闭它时停止了阻塞,一切都按照我的预期运行。

感谢您的建议。

答案 1 :(得分:5)

进一步的想法。

在JMS中,Connection是多线程的。会议及以下(消费者,制片人,消息等)are not thread-safe。如果您从多个线程访问任何非线程安全的东西,那么您有责任避免多线程访问。

您在下面显示的代码看起来就像是从几个线程调用Consumer上的方法。违反该规则。

关闭Connection对象可能更安全。没有线程冲突和任何明智的实现都可以正确地清理与Connection相关的资源。

答案 2 :(得分:3)

但是,在另一个线程上调用consumer.close()是不对的。您将需要进行连接。关闭将关闭该连接下的所有会话,消费者,生产者等。

答案 3 :(得分:2)

  1. 试试receive(long timeout),不要忘记检查返回的消息不是null
  2. 除了consumer.close()之外,您还可能会中断轮询线程 - 如果close()实施不当且未通知被阻止的接收方,则会将其唤醒。