我想安排一个每隔 X 小时执行一次的定期任务。我有一个用 Java 编写的服务,我正在考虑创建一个长时间运行的后台线程,只要服务启动就永远运行。如何确保我们每 X 小时执行一次任务?我的主机上的时钟漂移是我应该担心的问题吗?我知道如果 CPU 努力工作,时钟滴答的频率可能会改变。
编辑:我正在考虑在我的 spring 配置中添加一个 bean 来启动将定期执行我的任务的线程。
我想安排一个每隔 X 小时执行一次的定期任务。我有一个用 Java 编写的服务,我正在考虑创建一个长时间运行的后台线程,只要服务启动就永远运行。如何确保我们每 X 小时执行一次任务?我的主机上的时钟漂移是我应该担心的问题吗?我知道如果 CPU 努力工作,时钟滴答的频率可能会改变。
编辑:我正在考虑在我的 spring 配置中添加一个 bean 来启动将定期执行我的任务的线程。
Java 提供了一个java.util.Timer
类,旨在在后台线程上执行任务。其中一种操作模式是“定期重复执行”。根据您的确切需求,可以使用固定延迟和固定速率执行方法。
Java 5 添加了一个java.util.concurrent.ScheduledThreadPoolExecutor
比 更灵活的类Timer
,但也提供了固定延迟和固定速率的执行方法。
如果您需要这些不合适的精确时间,我不确定 Java 是否是合适的解决方案。您将开始进入实时系统领域。此时,您可能应该寻找其他选择。
如果你担心,写一个测试过程并在目标平台上运行它。使用您计划用于实际进程的功能(如ScheduledExecutorService
),安排一个任务以每 24 小时记录一次主机时间。如果主机不使用 NTP 来保持其时钟同步,也许您也可以调用一个计时 Web 服务并记录它。几天后,您应该清楚是否需要一种方法来纠正漂移。
我的猜测是,内置的调度程序每天的精确度会不到一秒。
我的主机上的时钟漂移是我应该担心的问题吗?
是的,使用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
});