如何在 Java Swing 应用程序中安排任务?

How to schedule a task in Java Swing application?

我有一个要求,需要复制我的一些文件并将其放入内部服务器。这需要定期发生,比如每天晚上 8 点。这也是 Swing 应用程序,运行 在我的本地 PC 中。我知道我可以使用 Java 安排任务,可以使用 java.util.TimeJodaTime 甚至更好的 Quartz Scheduler.

但是,问题来了。没有人会为了这个调度程序而让计算机 24 小时开机。据我所知,如果有人重新启动 PC,Java 调度器也会死掉。相反,一旦计划了任务,如果计算机已打开,计划的任务应该在每天晚上 8 点发生,无需人工干预。这意味着,无需重新启动应用程序并重新安排。

我描述的这个功能很常见,可以在所有病毒防护、基于windows 的警报等中看到。但是我如何在Java 中实现相同的功能?目前,如果我必须使用 windows 特定的解决方案,例如使用 JNI 或使用批处理文件等进行一些破解(我正在使用 windows),那也很好。

至少 java 可以吗?

为了在重新启动后安排并保持应用程序的安排(在 Java 中)是让 Java 应用程序重新启动并再次安排。

启动应用程序 运行:Run Java application at Windows startup,然后重新安排。

是正确的。这是有关在重新启动 Java 应用程序后设置时间表的编码的详细信息。

ScheduledExecutorService

如果使用 ScheduledExecutorService 界面来安排您的周期性任务,参数之一是 initialDelay。您指定等待任务第一次出现的时间量。在一次性延迟之后,您的任务将在另一个参数 period.

指定的每个时间量后重新发生

因此,在每次重新启动后,您将当前时刻与第一次 运行 所需的时刻进行比较。两者之间的时间跨度是您指定为 initialDelay 参数的量。

首先获取当前时刻。

ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime now = ZonedDateTime.now( z ) ;

在同一天设置您希望(目标)的时间。

LocalTime target = LocalTime.of( 20 , 0 );
ZonedDateTime then = ZonedDateTime.of( now.toLocalDate() , target , z );

检查今天的时间是否已经过去。如果过去,加一天到后一天。

if ( ! then.isAfter( now ) ) {  // If already past our target of 8 PM today, move to tomorrow.
    then = then.plusDays( 1 );
}

计算现在和我们想要运行我们的任务第一次出现的那个未来时刻之间的时间跨度(Duration)。

Duration initialDelay = Duration.between( now ; then );

指定我们希望将此任务 (period) 作为 Duration 对象 运行 的频率。

Duration period = Duration.ofHours( 24 );

将我们的一对 Duration 对象转换为一些分钟数、秒数或毫秒数或您想要的任何粒度。请记住,您的任务不会在您想要的那一瞬间完成。您的任务可能会由于线程执行的调度等原因而延迟,或者因为您的下一个 运行 任务正在等待前一个 运行 完成。所以我怀疑 TimeUnit.SECONDS 甚至几分钟对于日常任务来说已经足够精细了。

myScheduledExecutorService.scheduleAtFixedRate( 
    myRunnable , 
    initialDelay.getSeconds() , 
    period.getSeconds() , 
    TimeUnit.SECONDS 
) ; 

回顾一下:

  • initialDelay 是您的应用重新启动后使用一次的时间跨度,用于安排第一个 运行 任务。
  • period 是重复运行完成任务所用的时间跨度。