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