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

2022-09-04 08:39:18

javadoc for Session中,它指出:

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

因此,我理解您不应该同时使用来自两个不同线程 Session 对象。我不清楚的是,您是否可以从与其创建的线程不同的线程中使用 Session 对象(或队列等子对象)。

在我正在处理的情况下,我正在考虑将我的 Session 对象放入一个可用会话池中,任何线程都可以从中借用、使用,并在完成该池时返回到该池。

这是犹太洁食吗?

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


答案 1

我认为JMS 1.1规范中第4.4节的脚注提供了一些启示:

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

通过我对规范的阅读,只要您正确管理并发性,您想要执行的操作就可以了。


答案 2

可悲的是,JMS文档通常没有像我们想要的那样清晰或精确地编写:o(

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

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

请注意,“控制线程”的明确使用和“close()”是唯一的例外。

他们似乎在说,即使你使用异步消息消耗(即 setMessageListener)——这意味着你会在 JMS 创建的另一个线程上被调用回来接收消息——你也永远不允许从任何其他线程再次接触会话或相关对象,因为会话现在是“专用”给 JMS 传递线程的。例如,我假设这意味着您甚至不能从另一个线程调用message.acknowledge()。

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