避免在ManagedScheduledExecutorService中执行重复任务

时间:2015-10-21 07:48:58

标签: wildfly-8 java-ee-7

我正在开发wildfly 8.2上的Java EE 7应用程序,需要运行定期后台任务。我注入执行器服务并安排任务,这部分工作正常:

@Resource
private ManagedScheduledExecutorService executorService;

...

executorService.scheduleWithFixedDelay(() -> {
  try {
    // do some stuff
  } catch (Throwable t) {
    log.error("Error", t);
  }
}, 0, 1, TimeUnit.MINUTES);

现在(实际上很好)功能是在重新部署时保存计划任务,因此仍然在新部署中安排。

但是如何检测任务是否已经安排以避免多次安排?

我尝试使用ScheduledFuture并取消@PreDestroy上的任务 和@PrePassivate

reloadTreeFuture = executorService.scheduleWithFixedDelay(() -> {

...

@PreDestroy
@PrePassivate
protected void shutdown() {
  reloadTreeFuture.cancel(true);
}

只要相应的任务在取消触发时没有执行,这样就可以正常工作。由于任务长时间运行并且经常运行,因此在执行过程中遇到它的可能性有点高。

如果在任务仍在执行时触发取消,则取消似乎什么都不做。它立即返回,方法ScheduledFuture.isDone()也返回true,但是从日志中我可以看到任务仍然在后台执行,直到它遇到需要注入Bean的点,由于取消部署过程而无法使用它。然后,该流程以org.jboss.msc.service.ServiceNotFoundException - 结束,但仍会安排

  reloadTreeFuture.cancel(true);
  while (!reloadTreeFuture.isDone()) {
    Thread.sleep(200); // I know this is bad - it's just for testing
  }

基本问题:如何确保任务未安排两次(甚至更多)?

1 个答案:

答案 0 :(得分:0)

您可以记下每个任务的ID并在执行前检查它们。当然,这可能不是最好的解决方案,但它确实有效。