有很多方法可以做到这一点。
第一,您可以使用 EJB Timer 创建一个运行一次的进程,该进程将立即启动。这是在后台生成进程的好方法。 EJB 计时器与特定的会话 Bean 实现相关联。您可以将 EJB 计时器添加到您希望能够执行此操作的每个会话 Bean,或者您可以拥有一个会话 Bean,然后可以通过某种调度机制调用您的应用程序逻辑。
对我来说,我将一个可序列化的参数块连同一个符合特定接口的类名传递给一个通用会话 Bean,然后执行该类。这样我就可以轻松地为大多数东西设置背景。
关于 EJB 定时器的一个警告是 EJB 定时器是持久的。创建 EJB 计时器后,它会一直留在容器中,直到其作业完成或取消。问题在于,如果您有一个长时间运行的进程,并且服务器出现故障,那么当它重新启动时,该进程将继续并重新启动。请注意,这可能是一件好事,但前提是您的流程准备好重新启动。但是,如果您有一个简单的流程遍历“10,000 项”,如果服务器在第 9,999 项上出现故障,那么当它恢复时,您可以轻松地看到它只是从第 1 项开始。这一切都是可行的,只是需要注意的。
另一种后台处理方式是您可以使用 JMS 队列。将消息放入队列,处理程序会与应用程序的其余部分异步运行。
这里的聪明之处是,我也利用 Timer Bean 所做的工作是,您可以根据您配置系统拥有的 MDB 实例的数量来控制将运行多少“作业”。
因此,对于在多个并行块中运行进程的特定任务,我将任务分解为“片段”,然后将每个片段发送到 MDB 执行它们的消息队列中。如果我允许 10 个 MDB 实例,我可以让任何任务的 10 个“部分”同时运行。
这实际上工作得非常好。将进程拆分并通过 JMS 队列路由它有一点开销,但这基本上都是“启动时间”。一旦开始,您将获得真正的好处。
使用消息队列的另一个好处是您可以让实际长时间运行的进程在单独的机器上执行,或者您可以轻松地创建一个机器集群来处理这些进程。然而,界面是一样的,代码不知道有什么区别。
我发现,一旦您将长时间运行的进程置于后台,您可能会付出无法立即访问该进程的代价。也就是说,没有理由直接监视正在执行的类本身,只需让它们将有趣的信息和统计信息发布到数据库或 JMX 或其他任何东西,而不是拥有可以直接监视对象的东西,因为它共享相同的内存空间。
我能够轻松设置一个框架,让任务在 EJB 计时器或 MDB 分散队列上运行,任务是相同的,我可以监控它们的进度、停止它们等。
您可以结合分散技术来创建多个 EJB 计时器作业。 MDB 的免费优势之一是它充当了一个线程池,可以限制您的工作(因此您不会突然因过多的后台进程而使系统饱和)。您只需利用容器中的 EJB 管理功能即可“免费”获得此功能。
最后,Java EE 6 为 Session Bean 方法提供了一个新的“异步”(或其他)限定符。我不知道它是如何工作的细节,因为我还没有使用新的 Java EE 6 容器。但我想您可能不会只想为这个设施更换容器。