Большинство ответов на этот вопрос и следующие два вопроса предполагают, что миллисекунды в день всегда одинаковы .
Как запланировать периодическое задание в Java?
Как запускать определенную задачу каждый день в определенное время, используя ScheduledExecutorService?
Однако, это не так из-за экономии дневного света и дополнительных секунд.Это означает, что если ваша служба работает годами и точность таймера имеет значение, таймер с фиксированным периодом не является вашим выбором.
Итак, я хотел бы представить мой фрагмент кода для более гибкого таймера, чемjava.util.Timer
.
package szx;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.function.Function;
public class ScheduledExecutor {
public void scheduleRegularly(Runnable task, LocalDateTime firstTime,
Function<LocalDateTime, LocalDateTime> nextTime) {
pendingTask = task;
scheduleRegularly(firstTime, nextTime);
}
protected void scheduleRegularly(LocalDateTime firstTime,
Function<LocalDateTime, LocalDateTime> nextTime) {
new Timer().schedule(new TimerTask() {
@Override
public void run() {
scheduleRegularly(nextTime.apply(firstTime), nextTime);
pendingTask.run();
}
}, Date.from(firstTime.atZone(ZoneId.systemDefault()).toInstant()));
}
private volatile Runnable pendingTask = null;
}
Затем вы можете выполнять свою работу каждый день в 2 часа дня, вызывая вышеуказанный метод следующим образом.
new ScheduledExecutor().scheduleRegularly(() -> {
// do your task...
}, LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).withHour(14), thisTime -> thisTime.plusDays(1));
Основная идея кода заключается в следующем:пересчитать оставшееся время до следующего тика и каждый раз запускать новый таймер.