首页 文章

JMS:在一个线程上通过MessageConsumer.receive()读取是否可以,然后从另一个线程调用Session.commit()?

提问于
浏览
1

JMS会话的规范警告说,当SessionListener实例注册到Session时,Session对象/实例只能用于创建它们的线程 . 但是,当使用MessageConsumer对象(仅限)时,它没有说明线程不安全,或者更准确地说是"thread-bound" .

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

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

这个问题的答案也表明Sessions是线程约束的:Relationship between JMS connections, sessions, and producers/consumers

但是,作者可能会或可能不会做出一些假设,而且问题还在于写信息而不是阅读信息 .

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

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

How to continuously read JMS Messages in a thread and achnowledge them based on their JMSMessageID in another thread?

Reason for a JMS Session object to be used in a single threaded context

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

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

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

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

1 回答

  • 1

    也许你已经在规范中找到了一种方法 .

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

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

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

    你必须要注意

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

    因此,您必须确保 readcommit 不重叠 .

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

    [从法律角度来看:你承认你正在做一些“奇怪的” - 反对这个建议 . 我不会提供这样的软件 . ]

相关问题