1

JMS 会话的规范警告说,当 MessageListener 实例注册到 Session 时,只能在创建它们的线程上使用 Session 对象/实例。但是,在使用 MessageConsumer 对象(仅)时,它并没有说明线程不安全,或者更准确地说,“线程绑定”。

http://docs.oracle.com/javaee/1.3/api/javax/jms/Session.html

(通过“线程绑定”,我的意思是该对象只能在特定线程上使用,而不仅仅是在没有同步或其他协调的情况下在多个线程上使用它是不安全的)

这个问题的答案还表明会话是线程绑定的: JMS 连接、会话和生产者/消费者之间的关系

然而,作者可能会或可能不会做出一些假设,问题也更多是关于编写消息而不是阅读它们。

有人知道您是否可以在一个线程上的 Session 中读取消息,然后让另一个线程处理该消息并在该另一个线程上对消息(与会话)进行提交/回滚?只会从处理线程中针对 Session 调用提交(或回滚)——不会对 Connection / Session / MessageConsumer / Message 链进行其他调用。此外,在提交/回滚发生之前,不会使用 Session 再次读取。

以下 S/O 问题似乎密切相关,但不能令人满意地解决我的建议:

如何在一个线程中连续读取 JMS 消息并在另一个线程中根据它们的 JMSMessageID 确认它们?

在单线程上下文中使用 JMS 会话对象的原因

虽然我想在多个线程上使用 Session,但永远不会有重叠的消息请求/事务。

我试图避免进一步重构现有代码,所以我正在考虑做一些奇怪的事情,而不是在每个工作线程上都有一个 Session。

      • 编辑(7月26日) - - -

这个问题Using a JMS Session from different threads似乎暗示可以在不同线程上对会话进行同步操作,但我不确定引用了哪个版本的规范。

4

1 回答 1

1

也许您在规范中找到了一种方法。

来自Session http://docs.oracle.com/javaee/1.3/api/javax/jms/Session.html的文档的引用

Session 对象是用于产生和使用消息的单线程上下文。尽管它可以在 Java 虚拟机 (JVM) 之外分配提供者资源,但它被视为轻量级JMS 对象。

所以它是单线程的;并且创建一个并不昂贵。

而且你要注意

close 方法是唯一可以在另一个线程中执行其他会话方法时调用的会话方法。

因此,例如,您必须确保这一点read并且commit不重叠。

从技术角度来看,我会重构它;代码将更容易阅读/维护。资源处理(打开/关闭)将仅在一个线程(一种方法)中进行。这也将简化异常处理。

[从法律的角度来看:你承认你正在做一些“奇怪”的事情——违背了建议。我不会提供这样的软件。]

于 2013-07-26T11:23:42.630 回答