日期/时间的调用方法 [英] Call method at date/time

查看:95
本文介绍了日期/时间的调用方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am searching for a modern way to execute a given method at a given date/time (ZonedDateTime in particular).

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

I am aware of the Timer class and the Quartz library, as shown here (the threads include full solutions):

  • Java - Execute method on specific date [closed]
  • Call a method at fixed time in Java

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

But those threads are rather old and do not utilize the new Java features and library elements since then. In particular, it would be very handy to get hands on any kind of Future object, since they provide a simple mechanism to cancel them.

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

So please do not suggest solutions involving Timer or Quartz. Also, I'd like to have a vanilla solution, not using any external libraries. But feel free to also suggest those for the sake of Q&A.

推荐答案

ScheduledExecutorService

您可以使用ScheduledExecutorService(

ScheduledExecutorService

You can use the ScheduledExecutorService (documentation) class, which is available since Java 5. It will yield a ScheduledFuture (documentation) which can be used to monitor the execution and also cancel it.

尤其是方法:

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

其中

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

Submits a one-shot task that becomes enabled after the given delay.

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

But you can also look into the other methods, depending on the actual use case (scheduleAtFixedRate and versions accepting Callable instead of Runnable).

自从Java 8(Streams,Lambdas等)以来,由于在旧版TimeUnit和新版ChronoUnit之间(对于您的ZonedDateTime)提供了简便的转换方法,该类变得更加方便了,以及提供Runnable command作为lambda或方法引用的功能(因为它是FunctionalInterface).

Since Java 8 (Streams, Lambdas, ...) this class becomes even more handy, due to the availability of easy conversion methods between the old TimeUnit and the newer ChronoUnit (for your ZonedDateTime), as well as the ability to provide the Runnable command as lambda or method reference (because it is a FunctionalInterface).

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

Let's have a look at an example doing what you ask for:

// 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监视执行情况,并根据需要将其取消.示例:

You can then use the job to monitor the execution and also cancel it, if desired. Example:

if (!job.isCancelled()) {
    job.cancel(false);
}


注释

您可以在方法中将ZonedDateTime参数替换为Temporal,然后它还接受其他日期/时间格式.


Notes

You can exchange the ZonedDateTime parameter in the method for Temporal, then it also accepts other date/time formats.

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

Do not forget to shutdown the ScheduledExecutorService when you are done. Else you will have a thread running, even if your main program has finished already.

scheduler.shutdown();

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

Note that we use Instant instead of ZonedDateTime, since zone information is irrelevant to us, as long as the time difference is computed correctly. Instant always represents the time in UTC, without any weird phenomena like DST. (Although it does not really matter for this application, it is just cleaner).

这篇关于日期/时间的调用方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆