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

时间:2013-07-25 23:34:01

标签: java multithreading jms commit jms-session

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

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似乎表明可以在不同线程上对会话执行 synchronized 操作,但我不确定引用了哪个版本的规范。< / p>

1 个答案:

答案 0 :(得分:1)

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

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

的文档的引用
  

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

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

你必须注意

  

close方法是 only 会话方法,可以调用其他会话方法在另一个线程中执行

因此,您必须确保readcommit不重叠,例如。

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

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