执行者服务
定义一个Runnable(或Callable)。这意味着只需使用run 方法来遵守接口的约定。
在 lambda 语法中:
Runnable runnable =
() -> {
System.out.println( "Looking up fresh stock prices at " + Instant.now().toString() ) ;
}
;
接下来,学习现代 Java 中内置的 Executors 框架。见Oracle Tutorial。这个框架极大地简化了线程调度工作的棘手工作。
具体来说,您想使用ScheduledExecutorService。该接口用于调度任务在特定时间运行一次(实际上是在特定延迟到期后运行一次),或重复运行一个任务。你当然想要前者。
从Executors 类中获取一个实现。为了您的需要,我们只需要一个单线程。在其他情况下,您可能需要使用线程池。
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor() ;
指定等待多长时间,延迟,直到任务被执行。计算等待所需的经过时间。
指定您的目标日期。在实际工作中,我会验证日期确实在未来。
LocalDate localDate = LocalDate.of( 2020 , Month.FEBRUARY , 23 ) ;
我们需要一个特定的时刻,而不仅仅是一个日期。我想你会想要那天的第一刻。不要假设这是 00:00。在某些日期的某些区域中的某些日子可能会从另一个时间开始,例如 01:00。始终让 java.time 确定第一时刻。
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = localDate.atStartOfDay( z ) ;
从那个时区转换为 UTC。
Instant then = zdt.toInstant() ;
以 UTC 格式捕捉当前时刻。
Instant now = Instant.now() ;
将经过的时间计算为Duration。
Duration d = Duration.between( now , then ) ;
现在安排我们的任务在延迟到期后运行。我建议增加一点时间,以确保任何相关系统的所有时钟都顺利进入新的一天。加上午夜往往是计算的Witching Hour,有许多 cron 作业、日志滚动、实用程序和报告运行。也许增加几分钟或更长时间。
ses.scheduleWithFixedDelay( runnable , d.plusMinutes( 7 ).toMinutes() , TimeUnit.MINUTES);
您可以选择捕获返回的ScheduledFuture 来监控您的任务。
重要提示请务必在不再需要或关闭应用程序时正常关闭执行程序服务。否则,您的线程可能会在您的应用退出后继续在后台运行。
ses.shutdown() ;