为什么ScheduledExecutorService在第15秒关闭,但它仍然会执行第17和第20个任务?

时间:2017-05-24 02:53:58

标签: java threadpool

这是代码:

public class TimerTask {
  private final ScheduledExecutorService scheduler;
  private ScheduledFuture<?> scheduledFuture;

  TimerTask() {
    scheduler = Executors.newScheduledThreadPool(1);
  }

  private void startTimerTask() {
    Runnable printTask = createPrintTask();
    System.out.println(new Date());
    scheduledFuture = scheduler.scheduleAtFixedRate(printTask, 5, 2, TimeUnit.SECONDS);
    scheduler.schedule(() -> {
      if (scheduledFuture != null && !scheduledFuture.isCancelled()) {
        scheduledFuture.cancel(true);
        System.out.println(new Date());
      }
    }, 10, TimeUnit.SECONDS);

    scheduler.schedule(() -> {
      if (scheduledFuture != null || scheduledFuture.isCancelled()) {
        System.out.println(scheduledFuture.isDone() + "  " + scheduledFuture.isCancelled());
        scheduler.shutdown();
      }
    }, 15, TimeUnit.SECONDS);

    scheduler.schedule(() -> {
      if (scheduledFuture != null || scheduledFuture.isCancelled()) {
        System.out.println("danluo");
      }
    }, 17, TimeUnit.SECONDS);

    scheduledFuture = scheduler.scheduleAtFixedRate(printTask, 20, 2, TimeUnit.SECONDS);
  }

  private Runnable createPrintTask() {
    return () -> System.out.println("nsnnsn" + new Date());
  }

  public static void main(String []args) {
    TimerTask timerTask = new TimerTask();
    timerTask.startTimerTask();
  }

}

这是输出:

Wed May 24 10:39:06 CST 2017
nsnnsnWed May 24 10:39:11 CST 2017
nsnnsnWed May 24 10:39:13 CST 2017
nsnnsnWed May 24 10:39:15 CST 2017
Wed May 24 10:39:16 CST 2017
nsnnsnWed May 24 10:39:17 CST 2017
nsnnsnWed May 24 10:39:19 CST 2017
nsnnsnWed May 24 10:39:21 CST 2017
true  true
danluo

为什么它会在第17秒和第15秒之前执行第20个任务? 看起来很奇怪。你能帮我解答一下这个问题吗? 感谢。

它显示代码太多,我不知道为什么,所以我再添加一些解释。

2 个答案:

答案 0 :(得分:0)

当你说,

scheduler.schedule(() -> {
  if (scheduledFuture != null || scheduledFuture.isCancelled()) {
    System.out.println("danluo");
  }
}, 17, TimeUnit.SECONDS);

如果scheduledFuture不是null 它已被取消,那么您可以像一样阅读它这没有任何逻辑意义。如果它是null,则第二个测试将抛出空指针异常。因此,我只能得出你想要的结论

scheduler.schedule(() -> {
  if (scheduledFuture != null && !scheduledFuture.isCancelled()) {
    System.out.println("danluo");
  }
}, 17, TimeUnit.SECONDS);

将会读取

  

如果scheduledFuture不是null ,则已被取消。

因为当您结束任务时,您可能想继续执行任务。对于 scheduledFuture,间隔为二十秒,当你说scheduledFuture = scheduler.scheduleAtFixedRate时你会创建一个新的...... jvm注意到你不再引用旧{{1}实例 - 但你有一个以上,一个不能可以(对你而言)。为此使用新的参考名称。如果您需要安排多项任务,请制作scheduledFuture或使用List

答案 1 :(得分:0)

回答帖子标题中的问题为什么执行计划任务虽然ExecutorService是从ExecutorService.shutdown()的JavaDocs关闭的:

  

启动有序关闭,其中先前提交的任务已执行,但不会接受任何新任务。如果已经关闭,调用没有额外的效果。

因此,您的计划任务将一直运行,直到完成,然后ExecutorService本身才会停止。