EJB内部Thread.sleep的解决方案

时间:2012-04-20 07:41:43

标签: java java-ee jboss ejb ejb-3.0

我使用jboss5.1,EJB3.0和独立的java应用程序作为“订阅者”

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

问题是,如果订阅者从主题中获取消息,则需要返回足够快来侦听更多消息(否则如果其他消息将被发布,它将会错过它)

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

这样就可以确保所有订阅者在发布新消息之前都回去听。

我知道不建议在EJB内部使用Thread。

该场景的任何解决方案?

感谢, 射线。

3 个答案:

答案 0 :(得分:2)

恕我直言,你根本不需要让出版商的线程处于睡眠状态。根据定义,在使用JMS和消息驱动bean时,您可以保证将传递消息。唯一不能保证的是订单:Message Driven Beans可能会按照与订单发送顺序不同的顺序获取消息。

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

答案 1 :(得分: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);
         }
    });
}

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

完成后,这将主要允许您删除EJB中的Thread.sleep,这是邪恶的,并且是各种令人头疼的消息来源。

答案 2 :(得分:0)

我知道这个帖子已经老了,但我觉得不得不加上我的两分钱。我同意Kyiu上面所说的内容。

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

问题在于JMS的设计使得消息不会丢失。因此,MDB将消费消息,无论如何。此外,应该记住,MDB(像其他EJB一样)是容器管理的。为什么你认为只有一个你的MDB实例正在使用你的消息(除非你设计它是这样的,我相信并非如此)。