我正在寻找在给定日期/时间执行给定方法的现代(尤其是ZonedDateTime
)。
我知道Timer
类和 Quartz 库,如下所示(线程包括完整解决方案):
- java-在特定日期[封闭] 执行方法
- 在Java中固定时间调用方法
但是这些线程很旧,从那以后就不使用新的Java功能和库元素。特别是,携带任何类型的Future
对象非常方便,因为它们提供了一种简单的机制来取消它们。
因此,请不要建议涉及Timer
或 Quartz 的解决方案。另外,我想拥有一个 vanilla 解决方案,而不是使用任何外部库。但请随时为Q& a。
ScheduledExecutorService
您可以使用ScheduledExecutorService
(文档)类,该类可从Java 5开始使用,它将产生ScheduledFuture
(文档),该类别可用于监视执行并取消执行。
特别是该方法:
ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)
哪个
提交了一个单枪任务,该任务在给定延迟后启用。
但是,您也可以根据实际用例(scheduleAtFixedRate
和接受Callable
而不是Runnable
)的版本来研究其他方法。
由于Java 8(流,Lambdas,...),由于旧TimeUnit
和较新的ChronoUnit
(用于ZonedDateTime
)之间的简易转换方法,因此此类变得更加方便,并且能够提供Runnable command
作为lambda或方法参考(因为它是FunctionalInterface
)。
示例
让我们看看一个示例做您的要求:
// Somewhere before the method, as field for example
// Use other pool sizes if desired
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
public static ScheduledFuture<?> scheduleFor(Runnable runnable, ZonedDateTime when) {
Instant now = Instant.now();
// Use a different resolution if desired
long secondsUntil = ChronoUnit.SECONDS.between(now, when.toInstant());
return scheduler.schedule(runnable, secondsUntil, TimeUnit.of(ChronoUnit.SECONDS));
}
呼叫很简单:
ZonedDateTime when = ...
ScheduledFuture<?> job = scheduleFor(YourClass::yourMethod, when);
然后,您可以使用job
来监视执行,并在需要(如果需要)中取消执行。示例:
if (!job.isCancelled()) {
job.cancel(false);
}
注释
您可以在Temporal
的方法中交换ZonedDateTime
参数,然后接受其他日期/时间格式。
完成后,不要忘记关闭ScheduledExecutorService
。否则,即使您的主程序已经完成,您也会运行一个线程。
scheduler.shutdown();
请注意,我们使用Instant
而不是ZonedDateTime
,因为只要正确计算时间差,区域信息与我们无关。Instant
始终代表UTC中的时间,没有任何怪异现象(如 dst )。(尽管对于此应用程序并不重要,但它只是更干净)。