JMS Session 单线程是什么意思?

What does JMS Session single-threadedness mean?

JMS 会话及其相关构造(消息、消费者、生产者等)的线程不安全性的确切性质是什么?只是对它们的访问必须序列化,还是访问仅限于创建线程?

或者是一种混合情况,可以区分创建和使用,即一个线程只能创建它们,然后另一个线程可以是唯一使用它们的线程?最后一种可能性似乎与 this answer 中的陈述相矛盾 "In fact you must not use it from two different threads at different times either!"

但请考虑 ActiveMQ 文档中的 "Server Side" example code

服务器 class 有名为会话(Session 类型)和 replyProducer(MessageProducer 类型)的数据成员

(事实上,会话成员也在两个线程中使用:在一个线程中创建 replyProducer 成员,在另一个线程中创建消息。)

这个官方示例代码是意外运行还是设计使然?真的可以在一个线程中创建这样的对象,然后安排另一个线程使用它们吗?

(注意:在其他消息传递基础设施中,例如 Solace,可以指定发生回调的线程,可以利用它来绕过这个 "thread affinity of objects" 限制,但没有这样的 API 调用是在 JMS 中定义的,据我所知。)

JMS 规范指出,除非调用 Session.Close() 方法,否则不应跨线程使用会话对象。从技术上讲,如果对 Session 对象或其子对象(生产者、消费者等)的访问被序列化,则可以跨线程访问 Session 或其子对象。话虽如此,由于 JMS 是一个 API 规范,它的实现因供应商而异。有些供应商可能会严格执行线程亲和性,而有些则不会。因此,坚持 JMS 规范并相应地编写代码总是更好。

官方答案似乎是第 4.4 节的脚注。 "Session" 在 JMS 1.1 specification 中的第 60 页。

There are no restrictions on the number of threads that can use a Session object or those it creates. The restriction is that the resources of a Session should not be used concurrently by multiple threads. It is up to the user to insure that this concurrency restriction is met. The simplest way to do this is to use one thread. In the case of asynchronous delivery, use one thread for setup in stopped mode and then start asynchronous delivery. In more complex cases the user must provide explicit synchronization.

当然,特定的实现是否遵守这一点是另一回事。在 ActiveMQ 示例的情况下,代码是一致的,因为所有入站消息处理都是通过单个异步回调进行的。