2

我最近使用 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 提供了一些类似方向但不提供相同功能的东西。

我也感谢其他解决方案。

非常感谢!

4

1 回答 1

0

使用 Java SE 执行器(即ScheduledExecutorService)提交进行必要更新的 Runnable/Callable。

您将必须实现自己的ManagedTask/等价物ManagedTaskListener,但这应该可以通过您的 Runnable/Callable 实现轻松实现。

旁注:
当您使用 ManagedTask 时,这是 ManagedTask.LONGRUNNING_HINT=true在 ManagedTask 上设置的完美场景。例如:

managedTask.getExecutionProperties().put(ManagedTask.LONGRUNNING_HINT, "true");
于 2016-02-23T17:40:57.163 回答