使用来自不同线程的JMS会话

从Session的javadoc中可以看出:

Session对象是用于生成和使用消息的单线程上下文。

所以我理解你不应该同时使用来自两个不同线程的Session对象。 我不清楚的是,你是否可以从与其创建的不同的线程中使用Session对象(或者像Queue这样的子代)。

在我正在研究的情况下,我正在考虑将我的Session对象放入一个可用会话池中,任何线程都可以从它中借用,使用,并在完成后返回池中。

这是犹太人吗?

(使用ActiveMQ BTW,如果这会影响答案。)

我认为JMS 1.1规范第4.4节的脚注有一些亮点:

可以使用Session对象或其创建的线程数没有限制。 限制是多个线程不应同时使用会话的资源。 用户应确保满足此并发限制。 最简单的方法是使用一个线程。 在异步传送的情况下,使用一个线程在停止模式下进行设置,然后启动异步传送。 在更复杂的情况下,用户必须提供显式同步。

如果您正确管理并发性,通过我阅读规范您想要做的就是好的。

遗憾的是,JMS文档通常不像我们希望的那样清晰或精确地编写:o(

但阅读规范我现在相信你真的不应该从其他线程访问会话,即使你保证没有并发访问。 为我摆动它的javadoc的一点是:

一旦启动了连接,任何具有已注册消息监听器的会话都专用于向其传递消息的控制线程。 客户端代码使用此会话或来自另一个控制线程的任何组成对象是错误的。 唯一的例外是使用会话或连接关闭方法。

注意明确使用’控制线’和单独输出’close()’作为唯一的例外。

他们似乎在说,即使您正在使用异步消息消耗(即setMessageListener) – 这意味着您在JMS创建的另一个线程上回调以接收消息 – 您永远不会再次从中触摸会话或相关对象任何其他线程,因为会话现在“专用”到JMS传递线程。 例如,我认为这意味着你甚至无法从另一个线程调用message.acknowledge()。

话虽如此,我只是注意到我们没有遵守这个限制,并且还没有注意到任何不良影响(使用SonicMQ)。 但是当然如果你不遵守标准,所有的赌注都会被取消,所以我想我们需要遵守1线程的1会话规则来保持安全。