我使用jboss5.1,EJB3.0和独立的java应用程序作为“订阅者”
我有通过jms Topic向订阅者发布消息的机制。 当用户收到消息时,它需要做几个操作,直到它再次开始监听未来的消息。
问题是,如果订阅者从主题中获取消息,则需要返回足够快来侦听更多消息(否则如果其他消息将被发布,它将会错过它)
所以我的解决方案是在ejb发布者中将putThread.sleep()放置几秒钟。
这样就可以确保所有订阅者在发布新消息之前都回去听。
我知道不建议在EJB内部使用Thread。
该场景的任何解决方案?
感谢, 射线。
答案 0 :(得分:2)
此外,使用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实例正在使用你的消息(除非你设计它是这样的,我相信并非如此)。