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

时间:2015-05-15 15:20:02

标签: java swing time scheduled-tasks quartz-scheduler

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

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

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

至少这是可以用java吗?

2 个答案:

答案 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是重复运行任务时使用的时间范围。