【问题标题】:Java - ScheduledExecutorService: Execute task at terminationJava - ScheduledExecutorService:在终止时执行任务
【发布时间】:2015-05-07 12:32:10
【问题描述】:

我使用ScheduledExecutorService 以固定速率执行任务。下面是我的main方法的内容:

RemoteSync updater = new RemoteSync(config);
try  {
    updater.initialise();
    updater.startService(totalTime, TimeUnit.MINUTES);
} catch (Exception e) {
    e.printStackTrace();
}

RemoteSync实现了AutoCloseable(和Runnable)接口,所以我最初使用try-with-resources,像这样:

try (RemoteSync updater = new RemoteSync(config)) {
    ...
} catch (Exception e) {
   e.printStackTrace();
}

但是updater.startService()在调度任务后立即返回,所以updater.close()被提前调用,应用程序退出。

这里是RemoteSyncstartService()方法:

public void startService(int rate, TimeUnit unit) {
    ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
    service =
        scheduledExecutorService.scheduleWithFixedDelay(this, 1L,
        rate,
        unit);
}

理想情况下,我希望有这样的方法:

scheduledExecutorService.executeAtTermination(Runnable task)

这将允许我在调度程序实际停止时调用close(),不幸的是我不知道这种方法。

我能做的是阻止startService() 方法,如下所示:

while (!scheduledExecutorService.isTerminated()) {
    Thread.sleep(10000);
}

但这感觉肮脏和hackish。

欢迎提出任何建议。

【问题讨论】:

  • 也许您可以使用应用程序关闭挂钩。就像在this 讨论中一样。
  • 嗯,我听说过关闭挂钩。我会试一试。谢谢@nukie
  • @nukie 我最终使用了关机钩子,如果您愿意添加我会接受的答案。

标签: java executorservice autocloseable


【解决方案1】:

也许您可以使用应用程序关闭挂钩。就像在this 讨论中一样。

您可以在应用程序初始化的某个阶段添加这样的代码:

Runtime.getRuntime().addShutdownHook(new Thread() {
  public void run() {
    >>> shutdown your service here <<<
  }
});

【讨论】:

    【解决方案2】:

    您可以尝试scheduledExecutorService.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS), 可能在单独的线程中

    【讨论】:

    • 似乎是一个不错的选择,唯一的问题是没有设置超时。该应用程序可能会运行数天甚至数周。我能做的是检查服务是否已终止。如果没有(发生超时),我可以再次致电awaitTermination。不过感谢您的建议。