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问题似乎密切相关,但没有令人满意地解决我提出的建议:
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 回答
也许你已经在规范中找到了一种方法 .
Session http://docs.oracle.com/javaee/1.3/api/javax/jms/Session.html的文献引用
所以它是单线程的;并且创建一个并不昂贵 .
你必须要注意
因此,您必须确保
read
和commit
不重叠 .从技术角度来看,我会重构它;代码将更容易阅读/维护 . 资源处理(打开/关闭)仅在一个线程(一个方法)中 . 这也将简化异常处理 .
[从法律角度来看:你承认你正在做一些“奇怪的” - 反对这个建议 . 我不会提供这样的软件 . ]