调度周期性任务和时钟漂移

时间:2015-11-13 20:35:09

标签: java scheduling scheduler clock periodic-task

我想安排一个每X小时执行一次的定期任务。我有一个用Java编写的服务,我正在考虑创建一个长时间运行的后台线程,只要服务启动就会永久运行。我怎样才能确保每X小时执行一次任务?我主机上的时钟漂移是一个我应该担心的问题吗?我知道如果CPU正在努力工作,时钟滴答的频率可能会改变。

编辑:我正在考虑在我的spring配置中添加一个bean来启动线程,这会定期执行我的任务。

3 个答案:

答案 0 :(得分:3)

Java提供了一个java.util.Timer类,用于在后台线程上执行任务。其中一种操作方式是定期重复执行"。根据您的具体需要,可以使用固定延迟和固定速率执行方法。

Java 5添加了java.util.concurrent.ScheduledThreadPoolExecutor类,它比Timer更灵活,但也提供固定延迟和固定速率执行方法。

如果您需要这些不合适的精确计时,我不确定Java是否是合适的解决方案。您将开始进入实时系统领域。此时,您可能正在寻找其他选择。

答案 1 :(得分:0)

如果您担心,请编写测试流程并在目标平台上运行。使用您计划用于实际流程的功能(如ScheduledExecutorService),安排任务每24小时记录一次主机时间。如果主机不使用NTP来保持其时钟同步,也许您也可以调用一个计时Web服务并记录它。几天之后,你应该很清楚你是否需要一种方法来纠正漂移。

我的猜测是内置的调度程序每天精确到不到一秒钟。

答案 2 :(得分:0)

主机上的时钟漂移是我应该担心的问题吗?

是的,使用ScheduledThreadPoolExecutor时可能会出现时钟漂移。

CronScheduler是专门为防止时钟漂移而设计的。

用法示例:

Duration syncPeriod = Duration.ofMinutes(1);
CronScheduler cron = CronScheduler.create(syncPeriod);

// If you need just precisely "once every X hours", irrespective of the
// starting time
cron.scheduleAtFixedRate(0, X, TimeUnit.HOURS, runTimeMillis -> {
    // Do the task
});

// If you need "once every X hours" in terms of wall clock time,
// in some time zone:
ZoneId myTZ = ZoneId.systemDefault();
cron.scheduleAtRoundTimesInDay(Duration.ofHours(X), myTZ, runTimeMillis -> {
    // Do the task
});

有关scheduleAtRoundTimesInDay的信息,请参见Javadocs。