我有一个要求,我需要获取一些文件的副本并将其放入内部服务器。这需要定期发生,例如每天晚上8点。这是一个 Swing 应用程序,在我的本地PC上运行。我知道我可以使用Java安排任务,使用java.util.Time
,JodaTime
或更好Quartz Scheduler
。
但是,问题来了。没有人会为这个调度程序保持计算机24小时开启。据我所知,如果有人重新启动了PC,那么Java调度程序也会死掉。相反,一旦安排了任务,如果计算机已打开,则计划任务应该每天晚上8点发生,而无需人工干预。这意味着,无需再次重新启动应用程序并重新安排。
我描述的这个功能很常见,可以在所有病毒防护,基于Windows的警报等中看到。但是我如何在Java中实现相同的功能呢?目前,如果我必须使用特定于Windows的解决方案,例如使用JNI
或者使用批处理文件等等(我正在使用Windows),那也没关系。
至少这是可以用java吗?
答案 0 :(得分:3)
为了在重新启动后安排和保留应用程序(在Java中),要让Java应用程序重新启动并再次安排。
让应用程序在启动时运行:Run Java application at Windows startup然后重新安排。
答案 1 :(得分:1)
Answer by Nairn是正确的。以下是重新启动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
是重复运行任务时使用的时间范围。