JMS会话单线程性是什么意思



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

或者它是一个混合的情况下,可以区分创建和使用,即一个线程可以创建它们,然后另一个线程可以是唯一一个使用它们?最后一种可能性似乎与这个答案中的陈述相矛盾,即"事实上,您也不能在不同的时间从两个不同的线程中使用它!"

但是考虑ActiveMQ文档中的"服务器端"示例代码。

Server类的数据成员名为session(类型为session)和replyProducer(类型为MessageProducer),它们是

    在一个线程中创建的
  • :调用Server()构造函数,从而调用实际创建调用的setupMessageQueueConsumer()方法;和
  • 在另一个线程中使用:调用onMessage()异步回调的线程。

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

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

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

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

官方答案似乎是4.4节的脚注。JMS 1.1规范第60页上的"Session"。

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

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

最新更新