日期/时间的调用方法

时间:2019-03-06 08:56:40

标签: java datetime future java-time

我正在寻找一种在特定日期/时间(特别是ZonedDateTime)执行给定方法的现代方法。

我知道Timer类和 Quartz 库,如下所示(线程包括完整的解决方案):

但是这些线程很旧,从那时起就不再使用新的Java功能和库元素。特别地,动手使用任何类型的Future对象都非常方便,因为它们提供了取消它们的简单机制。

因此,请勿提出涉及Timer Quartz 的解决方案。另外,我想有一个 vanilla 解决方案,而不使用任何外部库。但也可以出于问答考虑而提出建议。

1 个答案:

答案 0 :(得分:3)

ScheduledExecutorService

您可以使用ScheduledExecutorServicedocumentation)类,该类自Java 5起可用。它将产生一个ScheduledFuturedocumentation),该类可用于监视执行并取消它。

特别是方法:

ScheduledFuture<?> schedule​(Runnable command, long delay, TimeUnit unit)

其中

  

提交一次任务,该任务在给定延迟后启用。

但是您还可以根据实际使用情况(scheduleAtFixedRate和接受Callable而不是Runnable的版本来研究其他方法。

自Java 8(Streams,Lambdas等)以来,由于旧的TimeUnit与新的ChronoUnit之间的简便转换方法的可用性(对于您的{ {1}},以及提供ZonedDateTime作为lambda或方法引用的功能(因为它是Runnable command)。


示例

让我们看一个示例,该示例完成您所要的工作:

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); } 参数替换为ZonedDateTime,然后它也接受其他日期/时间格式。

完成操作后,请不要忘记关闭Temporal。否则,即使您的主程序已经完成,您也将运行一个线程。

ScheduledExecutorService

请注意,我们会使用scheduler.shutdown(); 而不是Instant,因为只要正确计算了时差,区域信息就与我们无关。 ZonedDateTime始终以UTC表示时间,没有任何 DST 之类的奇怪现象。 (尽管对于此应用程序并不重要,但它更干净)。