Die meisten Antworten auf diese Frage und die beiden folgenden Fragen davon ausgehen, dass die Millisekunden pro Tag immer gleich sind .
Wie plant man eine periodische Aufgabe in Java?
Wie kann man eine bestimmte Aufgabe jeden Tag zu einer bestimmten Zeit mit ScheduledExecutorService ausführen?
Dies ist jedoch aufgrund der Sommerzeit und der Schaltsekunden nicht richtig. Das bedeutet, dass, wenn Ihr Dienst jahrelang läuft und die Genauigkeit der Zeitschaltuhr wichtig ist, ist eine Zeitschaltuhr mit fester Zeitdauer nicht die richtige Wahl.
Daher möchte ich meinen Codeschnipsel für einen flexibleren Timer als den 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;
}
Dann können Sie Ihren Auftrag täglich um 2 Uhr nachmittags ausführen, indem Sie die oben genannte Methode wie folgt aufrufen.
new ScheduledExecutor().scheduleRegularly(() -> {
// do your task...
}, LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).withHour(14), thisTime -> thisTime.plusDays(1));
Die Grundidee hinter dem Code ist es, die verbleibende Zeit bis zum nächsten Tick neu zu berechnen und jedes Mal einen neuen Timer zu starten.