为了账号安全,请及时绑定邮箱和手机立即绑定

在日期/时间调用方法

在日期/时间调用方法

慕田峪9158850 2022-07-20 16:53:50
我正在寻找一种在给定日期/时间(特别是)执行给定方法的现代方法。ZonedDateTime我知道Timer类和Quartz库,如此处所示(线程包括完整的解决方案):Java - 在特定日期执行方法[关闭]Java中固定时间调用方法但这些线程相当陈旧,从那时起就不再使用新的 Java 特性和库元素。特别是,获得任何类型的Future对象都非常方便,因为它们提供了一种简单的机制来取消它们。所以请不要建议涉及Timer或Quartz的解决方案。另外,我想要一个普通的解决方案,不使用任何外部库。但是,为了问答,也可以随意提出这些建议。
查看完整描述

1 回答

?
眼眸繁星

TA贡献1873条经验 获得超9个赞

ScheduledExecutorService

您可以使用自 Java 5 起可用的ScheduledExecutorService( documentation ) 类。它将产生一个ScheduledFuture( documentation ),可用于监视执行并取消它。


具体来说,方法:


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

哪个


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


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


由于 Java 8 (Streams, Lambdas, ...) 这个类变得更加方便,因为TimeUnit新旧ChronoUnit(对于你的ZonedDateTime)之间的简单转换方法的可用性,以及提供Runnable commandas lambda 或方法的能力参考(因为它是 a 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这样的奇怪现象。(虽然对于这个应用程序来说并不重要,但它更干净)。



查看完整回答
反对 回复 2022-07-20
  • 1 回答
  • 0 关注
  • 84 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信