在日期/时间调用方法

问题描述 投票:2回答:1

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

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

但是那些线程相当陈旧,从那以后就不再使用新的Java特性和库元素了。特别是,接触任何类型的Future对象都非常方便,因为它们提供了一种取消它们的简单机制。

所以请不要建议涉及Timer或Quartz的解决方案。此外,我想要一个vanilla解决方案,而不是使用任何外部库。但是,为了问答,请随意提出这些建议。

java datetime future java-time
1个回答
3
投票

ScheduledExecutorService

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

特别是,方法:

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

哪一个

提交在给定延迟后启用的一次性任务。

但您也可以查看其他方法,具体取决于实际用例(scheduleAtFixedRate和接受Callable而不是Runnable的版本)。

自从Java 8(Streams,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);
}

笔记

您可以在ZonedDateTime的方法中交换Temporal参数,然后它也接受其他日期/时间格式。

完成后别忘了关闭ScheduledExecutorService。否则,即使您的主程序已经完成,您也将运行一个线程。

scheduler.shutdown();

请注意,我们使用Instant而不是ZonedDateTime,因为区域信息与我们无关,只要正确计算时差即可。 Instant总是以UTC表示时间,没有像DST这样的奇怪现象。 (虽然这个应用程序并不重要,但它更简洁)。

© www.soinside.com 2019 - 2024. All rights reserved.