我最近使用 GlassFish / Payara 构建了一个 Java EE 7 Web 应用程序。Web 应用程序在底层操作系统上按需启动长时间运行的任务(> 2 小时)。这些任务基本上是用 Python、Ruby 或 Java 编写并使用命令行 (Apache Commons Exec) 执行的其他程序或脚本。由于我想通知用户任务的当前状态并让他能够取消正在运行的任务,因此我使用了以下 Java EE 功能和库。
以下列表简要描述了我决定使用特定 Java EE 功能或外部库的原因。
- ManagedExecutorService
- 使用@Resource 注入,允许我对 Runnables 进行排队并在自己的线程中执行它们
- ManagedTaskListener 实现
- 这就是我实际上决定使用 ManagedExecutorService 并在应用程序服务器中运行线程的原因
- 该界面给了我四个非常方便的方法(taskSubmitted、taskAborted、taskDone 和 taskStarting)
- 这使我能够更新长期运行的任务状态 (JPA) 并在发生状态更改时通知用户
- 可运行的托管任务实现
- 在这里,我通过覆盖 run() 方法定义了实际的长时间运行任务
- 为了对状态变化做出反应,我还注册了 ManagedTaskListener 实现,如前所述
- Apache Commons Exec 实用程序
- 要实际执行长时间运行的任务,Runnable 和 ManagedTask 实现只需使用 apache commons exec
- 为了能够取消长时间运行的进程,我为每个 DefaultExecutor 设置了一个 ShutdownHookProcessDestroyer
- 使用 defaultExecutor.getWatchdog().destroyProcess(); 这让我可以杀死正在运行的任务
我知道将 ManagedExecutorService 与 ManagedTasks 结合使用来执行如此长时间运行的任务并不是最好的主意,但它工作得相当稳定。
但是知道我想在不同的物理机器上运行这些长时间运行的任务,并只使用 Java SE 来执行它们。这意味着我没有 ManagedExecutorService,因此没有 ManagedTaskListener 接口。
有没有人有这种情况的经验?也许有提供类似功能的库。我认为 Google Guava 提供了一些类似方向但不提供相同功能的东西。
我也感谢其他解决方案。
非常感谢!