1

我正在使用 jboss5.1、EJB3.0 和独立的 Java 应用程序作为“订阅者”

我有通过 jms 主题向订阅者发布消息的机制。当订阅者收到消息时,它需要做一些操作,直到它再次开始监听未来的消息。

问题是,如果订阅者从主题中收到消息,它将需要足够快地返回以侦听更多消息(否则在发布另一条消息的情况下它将错过它)

所以我的解决方案是将Thread.sleep() 在ejb 发布者中放置几秒钟。

这种方式会确保所有订阅者在发布新消息之前都回去收听。

我知道不建议在 EJB'S 中使用 Thread。

这种情况的任何解决方案?

谢谢,雷。

4

3 回答 3

2

恕我直言,您根本不需要让发布者的线程处于睡眠状态。根据定义,当使用 JMS 和消息驱动 bean 时,您可以保证消息将被传递。唯一不能保证的是顺序:消息驱动 Bean 可能以不同于它们发送顺序的顺序获取消息。

此外,使用 JMS 的全部意义在于允许您异步发送消息(即使您实际上可以将队列/主题配置为同步工作)

于 2012-04-20T07:56:39.253 回答
1

好的,所以您的问题实际上是您在处理消息时停止侦听 JMS 队列,然后重新注册自己。当然,您可能会在处理前一条消息时错过消息。

我建议永远不要从 JMS 队列中注销自己,并且为了确保您一次处理一条消息,您可以使用一个线程池来推送您的处理。

例如,如果以前你有这样的事情:

public void onNewJMSMessage(JMSMessage message) {
    unregisterMySelf();
    processMessage(message);
    registerMySelf();
}

改用这个:

像这样启动一个类成员:

private ExecutorsService processingPool = Executors.newSingleThreadExecutor();

public void onNewJMSMessage(final JMSMessage message) {
    processingPool.submit(new Runnable() {

         @Override
         public void run() {
              processMessage(message);
         }
    });
}

这将保证一次只处理一条消息(如果封闭类是唯一的,否则您将必须设置一个单例以确保单线程池的唯一性)。

完成之后,这将主要允许您Thread.sleep在 EJB 中删除它,这是邪恶的,也是各种令人头疼的根源。

于 2012-04-20T14:04:28.663 回答
0

我知道这条线很旧,但我觉得有必要加两分钱。我同意Kiu上面所说的。

根据 EJB2 规范,企业 bean 不应该管理线程。我不确定最新的规范对此有什么说法,但如果这已经改变,我会感到震惊。

问题是 JMS 被设计成消息不会丢失。因此,无论如何,MDB 都会使用这些消息。此外,应该记住 MDB(与其他 EJB 一样)是容器管理的。为什么您认为只有一个 MDB 实例在使用您的消息(当然,除非您将其设计为那样,我敢肯定情况并非如此)。

于 2016-07-12T00:55:06.323 回答