2

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

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

4

3 回答 3

3

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

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

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

于 2015-11-13T20:46:53.227 回答
0

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

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

于 2015-11-14T00:16:47.133 回答
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.

于 2020-01-29T14:19:17.720 回答