【问题标题】:Using a JMS Session from different threads使用来自不同线程的 JMS 会话
【发布时间】:2011-01-30 05:55:37
【问题描述】:

来自Session 的 javadoc 它指出:

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

所以我知道您不应该同时使用来自两个不同线程的 Session 对象。我不清楚的是,您是否可以使用与它创建的线程不同的线程中的 Session 对象(或队列等子对象)。

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

这是犹太洁食吗?

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

【问题讨论】:

    标签: java multithreading jms


    【解决方案1】:

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

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

    一旦建立连接, 任何带有注册消息的会话 listener(s) 专用于线程 将消息传递到的控制 它。客户端代码是错误的 使用此会话或其任何 来自另一个的组成对象 控制线程。唯一的例外 这是使用会话或 连接关闭方法。

    注意“控制线程”的明确使用和“close()”的单独使用作为唯一的例外。

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

    话虽如此,我只是注意到我们没有遵守这个约束,并且还没有注意到任何不良影响(使用 SonicMQ)。但当然,如果您不遵守标准,所有赌注都将失败,所以我想我们需要遵守 1-thread 1-session 规则以确保安全。

    【讨论】:

    • 本页的最后一篇文章也支持对线程约束的这种解释:stackoverflow.com/questions/1669746/…
    • 会话必须限制在您控制的单个线程中(用于阻塞写入/读取),或者由 JMS 分配用于异步侦听的单个线程。 => 1) 对于并发读/写,必须使用单独的会话。 2)并行消费,必须使用多个Session。另请参阅onjava.com/pub/a/onjava/excerpt/jms_ch2/index.html?page=4#78858 的精彩解释
    • 请注意,确实正如 T.Rob 所说,单线程可以随时间而变化,只要确保施加发生前的关系。
    【解决方案2】:

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

    对可以使用 Session 对象或其创建的线程的数量没有限制。限制是一个 Session 的资源不应该被多个线程同时使用。由用户确保满足此并发限制。最简单的方法是使用一个线程。异步投递的情况下,使用一个线程在stopped模式下设置,然后开始异步投递。在更复杂的情况下,用户必须提供显式同步。

    根据我对规范的阅读,只要您正确管理并发性,您想做的事情就可以了。

    【讨论】:

    • 任何方式都可以将链接添加到规范中的引用来自的页面——哪个版本或包/类 javadoc(如果这是源)?谢谢。
    • 完成。请参阅 P60 底部的脚注。
    猜你喜欢
    • 2020-02-01
    • 2015-07-23
    • 2011-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-31
    • 2011-11-01
    • 2021-12-03
    相关资源
    最近更新 更多