ScheduledExecutorService
您可以使用ScheduledExecutorService
(文档 https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/ScheduledExecutorService.html) 类,从 Java 5 开始可用。它将产生一个ScheduledFuture
(文档 https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/ScheduledFuture.html) 可用于监视执行并取消它。
具体来说,该方法:
ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)
which
提交在给定延迟后启用的一次性任务。
但您也可以根据实际用例研究其他方法(scheduleAtFixedRate
和版本接受Callable
代替Runnable
).
从 Java 8(Streams、Lambdas 等)开始,这个类变得更加方便,因为旧版本之间可以使用简单的转换方法。TimeUnit
和较新的ChronoUnit
(为您ZonedDateTime
),以及提供的能力Runnable command
作为 lambda 或方法引用(因为它是FunctionalInterface
).
Example
让我们看一个执行您要求的示例:
// 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);
}
Notes
您可以交换ZonedDateTime
方法中的参数为Temporal
,那么它也接受其他日期/时间格式。
不要忘记关闭ScheduledExecutorService
当你完成时。否则,即使您的主程序已经完成,您也会有一个线程正在运行。
scheduler.shutdown();
请注意,我们使用Instant
代替ZonedDateTime
,由于时区信息与我们无关,只要正确计算出时差即可。Instant
始终表示 UTC 时间,没有任何weird像这样的现象DST。 (虽然这对于这个应用程序来说并不重要,但它只是更干净)。