【问题标题】:javax.jms.MessageConsumer hangs on receive when consumer closed消费者关闭时 javax.jms.MessageConsumer 挂起接收
【发布时间】:2011-12-21 20:32:32
【问题描述】:

根据 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() 方法,它将阻塞直到超时到期。

一切对我来说都是正确的,希望有人能告诉我我做错了什么。

【问题讨论】:

  • JMS 是众所周知的特定于底层实现。如果您说出您使用的是哪一个,将会有所帮助。
  • 感谢您的回复。它是 IBM MQ 7.0.0.2

标签: java jms ibm-mq


【解决方案1】:

我已经解决了这个问题,我没有在任何地方做 connection.start() 。一旦我把它放进去,当我关闭它时 MessageConsumer.receive() 停止阻塞,一切都按我预期的那样工作。

感谢您的建议。

【讨论】:

    【解决方案2】:

    再想一想。

    在 JMS 中,连接是多线程的。会话及以下(消费者、生产者、消息等)are not thread-safe。如果您从多个线程访问任何非线程安全的东西,您有责任避免多线程访问。

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

    关闭 Connection 对象可能更安全。没有线程冲突,任何合理的实现都会做正确的事情来清理与连接相关的资源。

    【讨论】:

      【解决方案3】:

      但是,在另一个线程上调用 consumer.close() 仍然不是正确的做法。您需要建立一个连接。关闭它将负责关闭该连接下的所有会话、消费者、生产者等。

      【讨论】:

        【解决方案4】:
        1. 试试receive(long timeout),别忘了检查返回的消息不是null
        2. 除了consumer.close(),您还可以中断轮询线程 - 如果close() 实施不当并且没有通知阻塞的接收器,这将唤醒它。

        【讨论】:

        • 谢谢。我尝试了接收()的超时版本,但我遇到了同样的问题 - 它只是在超时的剩余时间内阻塞,所以我的应用程序在超时完成之前不会关闭,这不是我想要的。
        • 是的,另一件事 - 如果这是关闭整个应用程序的一部分,请关闭所有对象(MessageConsumerSessionConnection)。
        猜你喜欢
        • 2012-04-18
        • 1970-01-01
        • 1970-01-01
        • 2020-04-07
        • 1970-01-01
        • 1970-01-01
        • 2013-08-25
        • 2019-05-23
        • 2011-03-05
        相关资源
        最近更新 更多