【问题标题】:ScheduledExecutorService - Check if scheduled task has already been completedScheduledExecutorService - 检查计划任务是否已经完成
【发布时间】:2014-02-21 22:04:10
【问题描述】:

我有一个服务器端应用程序,客户端可以请求重新加载配置。如果客户端请求重新加载配置,这不应该立即完成,而是延迟 1 分钟。如果另一个客户端也在同一分钟内请求重新加载配置,则应忽略此请求。

我的想法是使用 ScheduledExecutorService 来安排任务,例如:

 ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
 service.schedule(new LoadConfigurationTask(), 1, TimeUnit.MINUTES);

 public class LoadConfigurationTask Runnable {
    public void run() {
      // LoadConfiguration
    }
 }

如何检查 LoadConfigurationTask 是否已计划但尚未执行,以便能够在重新加载配置之前忽略进一步的请求?

【问题讨论】:

  • 如果重新加载配置任务正在运行怎么办 - 是否也应该忽略另一个请求?如果任务在 1 毫秒前完成怎么办?
  • 否,如果正在运行,应该安排新任务

标签: java multithreading timer singleton


【解决方案1】:

您可以像这样简单地获得对 ScheduledFuture 的引用:

ScheduledFuture<?> schedFuture = service.schedule(new LoadConfigurationTask(), 1, TimeUnit.MINUTES);

现在有了未来,你可以检查任务是否完成:

schedFuture.isDone();

或者更好的是,检查执行开始前还剩多少时间:

schedFuture.getDelay(TimeUnit.MINUTES);

不需要外部变量来跟踪状态。

【讨论】:

  • 请注意,这可能不会完全返回您想要的内容。例如,我创建了一个运行 1 分钟的任务。在前 10 秒内调用 future.cancel()。未来会为isDone() and isCancel() 返回true,但是任务会继续运行,直到完成 1 分钟。
  • @user3758745 您指出了一个重要的点,这与Java处理线程的方式有关。一旦工作开始,几乎没有办法从 JVM 内部阻止它。调用 future.cancel(true) 将发送一个中断信号,但前提是线程被编码为正确处理中断信号。随意查看答案stackoverflow.com/questions/3976344/…
  • 如果您使用 ScheduledFuture.cancel(false) 取消任务并且它是长时间运行的,那么 SchedFuture.isDone() 将为 true,但实际上该任务会继续运行。可能最好的方式是“Tim B”所引用的。
【解决方案2】:

最简单的方法就是设置一个AtomicBooleanhttp://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicBoolean.html

启动任务时设置为true,任务完成时设置为false,除非设置为false,否则不再启动。

确保在 finally 块中设置为 false,这样您就不会在不取消设置的情况下意外退出。

【讨论】:

    猜你喜欢
    • 2015-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-06
    • 2020-08-28
    • 1970-01-01
    • 2018-04-18
    • 2014-07-22
    相关资源
    最近更新 更多