为什么scheduleOnce每次都在app关闭时运行?

时间:2014-05-05 03:10:08

标签: scala playframework akka

我有Play 2应用。

并编写类似的东西。 所以,我在启动模式和运行模式下运行应用程序。

val calendar = Calendar.getInstance()
calendar.set(Calendar.HOUR_OF_DAY, 19)
calendar.set(Calendar.MINUTE, 0)
calendar.set(Calendar.SECOND, 0)
calendar.set(Calendar.MILLISECOND, 0)

val now = new Date()

val timeDifference = calendar.getTime.getTime - now.getTime

if (timeDifference >= 0) {
  val initialDelay = Duration.create(timeDifference, duration.MILLISECONDS)

  Akka.system.scheduler.scheduleOnce(initialDelay, new Runnable {
    override def run() {
      LOGGER.error(System.lineSeparator() +
        "=================================================" + System.lineSeparator() +
        "|   Forming and send report                     |" + System.lineSeparator() +
        "=================================================" + System.lineSeparator()
      )
    }
  })
}

为什么 scheduleOnce 会在关机时运行?

1 个答案:

答案 0 :(得分:2)

您在此处看到的行为实际上会影响默认计划程序(LightArrayResolverScheduler)中计划的所有任务,无论它们是使用schedule还是scheduleOnce进行安排的。如果您查看close上的LightArrayResolverScheduler方法,您会看到以下逻辑:

override def close(): Unit = Await.result(stop(), getShutdownTimeout) foreach {
  task =>
    try task.run() catch {
      case e: InterruptedException => throw e
      case _: SchedulerException   => // ignore terminated actors
      case NonFatal(e)             => log.error(e, "exception while executing timer task")
    }
}

基本上,在计时器关闭期间,它会收集所有未完成的任务并按顺序执行它们。我认为如果你的日程安排只是向演员发送消息(而不是使用Runnable),这将不是什么大问题,因为这些演员希望被这一点终止并导致什么都没发生(死信)。

如果要避免此行为,可以将调用结果存储到scheduleOnce并在启动关闭过程之前先将其明确取消。