15

我正在开发一项服务,该服务假设每小时开始,准确地重复整点(下午 1:00、下午 2:00、下午 3:00 等)。

我尝试了以下操作,但有一个问题是我第一次必须在开始时准确地运行程序,然后这个调度程序会重复它。

ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleWithFixedDelay(new MyTask(), 0, 1, TimeUnit.HOURS);

无论我何时运行程序,有什么建议可以重复我的任务吗?

问候, 伊姆兰

4

4 回答 4

16

我也会为此建议使用Quartz。但是可以使用 initialDelay 参数使上面的代码在一小时开始时首先运行。

Calendar calendar = Calendar.getInstance();
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new MyTask(), millisToNextHour(calendar), 60*60*1000, TimeUnit.MILLISECONDS);



private static long millisToNextHour(Calendar calendar) {
    int minutes = calendar.get(Calendar.MINUTE);
    int seconds = calendar.get(Calendar.SECOND);
    int millis = calendar.get(Calendar.MILLISECOND);
    int minutesToNextHour = 60 - minutes;
    int secondsToNextHour = 60 - seconds;
    int millisToNextHour = 1000 - millis;
    return minutesToNextHour*60*1000 + secondsToNextHour*1000 + millisToNextHour;
}
于 2012-04-18T07:34:37.957 回答
10

millisToNextHourkrishnakumarp 的答案中的方法可以在 Java 8 中变得更加紧凑和直接,这将导致以下代码:

public void schedule() {
    ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
    scheduledExecutor.scheduleAtFixedRate(new MyTask(), millisToNextHour(), 60*60*1000, TimeUnit.MILLISECONDS);
}

private long millisToNextHour() {
    LocalDateTime nextHour = LocalDateTime.now().plusHours(1).truncatedTo(ChronoUnit.HOURS);
    return LocalDateTime.now().until(nextHour, ChronoUnit.MILLIS);
}
于 2016-03-16T09:05:29.913 回答
7

如果你负担得起使用外部库,那么Quartz提供了非常灵活且易于使用的调度模式。例如cron,模式应该非常适合您的情况。下面是一个安排某个Job每小时执行的简单示例:

quartzScheduler.scheduleJob(
    myJob, newTrigger().withIdentity("myJob", "group")
                       .withSchedule(cronSchedule("0 * * * * ?")).build());

查看教程示例,找到适合您口味的配方。他们还展示了如何处理错误。

于 2012-04-18T06:52:52.993 回答
1

如果您在服务中使用spring,则可以直接使用基于注解的调度程序@Schedule注解,该注解将cron表达式作为参数或以毫秒为单位的延迟,只需将此注解添加到您要执行的方法上方,此方法将是执行。享受...........

于 2012-04-18T07:09:24.310 回答