我正在编写一个JEE7 / Glassfish 4应用程序,它从外部队列(RabbitMQ)读取数据并对其进行处理。它需要一个方法(我想是一个EJB方法),它包含一个永不退出的循环来读取队列。我想因为这个循环永远不会退出,所以它需要在一个单独的线程上。我的问题是,在JEE7应用程序中执行此操作的正确方法是什么?
这可能很明显,但ReadQueue()方法需要在应用启动时自动启动,并且必须永久运行。
ManagedExecutorService适用于此吗?
答案 0 :(得分:1)
启动具有无限循环的线程,定期轮询队列通常不是一个好主意。队列的性质表明异步,事件驱动的处理。对于JEE世界中的此类问题,您有MDBs。这里唯一的问题是MDB需要JMS队列提供程序,但RabbitMQ使用不同的协议(AMQP)。您需要一个JMS-AMQP桥来完成这项工作。可能是Qpid JMS但不保证它会起作用。
答案 1 :(得分:0)
ManagedExecutorService正是您想要用于此目的的。
这项服务在JEE中的可用性是一个很大的好处。在过去,我们基本上只是忽略了这些指导方针并自己管理了所有这些内容。
MES允许您捕获调用组件的上下文信息,并将您的任务绑定到容器的生命周期。这些在JEE环境中都非常重要。
至于在哪里开始任务,你基本上有两个选择。
一,您可以使用ServletContextListener,并在容器启动期间启动任务。
其二,您可以使用@Singleton EJB,并使用其生命周期方法来启动任务。
如果从ServletContextListener启动任务,那么任务将像在WAR环境中一样运行。如果从@Singleton启动它,它将在Session Beans环境中运行(这主要与JNDI的显示方式有关)。
无论哪种方式,您只需要担心通过这些机制启动任务。您应该依赖ManagedTaskListener.taskAborted接口方法来关闭任务。
理论上,您可以使用在关闭期间发送到您的任务的Thread.interrupt。我自己从来没有好运,我依靠外部机制来告诉长时间运行的任务被关闭。
我希望我可以亲身体验这个新设施,但我还没有机会尝试一下。但是根据规范,这就是你想要做的。
答案 2 :(得分:-1)
以下是创建永不退出的线程的一种方法:
public class HelloRunnable implements Runnable {
public void run() {
while (true) {
// do ReadQueue() here
}
}
public static void main(String args[]) {
(new Thread(new HelloRunnable())).start();
}
}