根据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()方法,它将一直阻塞,直到超时到期。
一切看起来都对我好,希望有人可以告诉我我做错了什么。
答案 0 :(得分:5)
我已经对问题进行了排序,我没有在任何地方进行connection.start()。一旦我把它放入,MessageConsumer.receive()在我关闭它时停止了阻塞,一切都按照我的预期运行。
感谢您的建议。
答案 1 :(得分:5)
进一步的想法。
在JMS中,Connection是多线程的。会议及以下(消费者,制片人,消息等)are not thread-safe。如果您从多个线程访问任何非线程安全的东西,那么您有责任避免多线程访问。
您在下面显示的代码看起来就像是从几个线程调用Consumer上的方法。违反该规则。
关闭Connection对象可能更安全。没有线程冲突和任何明智的实现都可以正确地清理与Connection相关的资源。
答案 2 :(得分:3)
但是,在另一个线程上调用consumer.close()是不对的。您将需要进行连接。关闭将关闭该连接下的所有会话,消费者,生产者等。
答案 3 :(得分:2)
receive(long timeout)
,不要忘记检查返回的消息不是null
。consumer.close()
之外,您还可能会中断轮询线程 - 如果close()
实施不当且未通知被阻止的接收方,则会将其唤醒。