Как планировать задачу для запуска каждого часа

Я разрабатываю услугу, которая предполагает начало каждого часа, повторяющегося точно в час (1:00 PM, 2:00 PM, 3:00 PM и т.д.).

Я пробовал следовать, но у меня есть одна проблема: я впервые должен запустить программу именно в начале часа, а затем этот планировщик повторит ее.

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

Любое предложение повторить мою задачу независимо от того, когда я запускаю программу?

С уважением, Имран

Ответ 1

Я также предложил бы 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;
}

Ответ 2

Если вы можете позволить себе использовать внешнюю библиотеку, Quartz обеспечивает очень гибкие и простые в использовании режимы планирования. Например, режим cron должен быть идеальным для вашего случая. Ниже простой пример планирования определенного Job, который должен выполняться каждый час:

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

Посмотрите tutorial и examples найти, какие формулировки соответствуют вашим вкусам. Они также показывают, как бороться с ошибками.

Ответ 3

Метод millisToNextHour в krishnakumarp answer можно сделать более компактным и понятным в 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);
}

Ответ 4

Если вы используете spring в своей службе, чем можете напрямую использовать аннотацию на основе планировщика @Schedule, которая принимает выражение cron в качестве параметра или задержку в миллисекундах, просто добавьте эту аннотацию выше метода, который вы хотите выполнить и этот метод будет выполнен. Наслаждайтесь...........