我有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 会在关机时运行?
答案 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
并在启动关闭过程之前先将其明确取消。