HOWTO · Java
Wie man in Java einige Sekunden verzögert
Erfahren Sie, wann Sie Thread.sleep() für eine blockierende Pause verwenden und wann Sie verzögerte oder wiederkehrende Aufgaben in Java planen sollten.
Auf dieser Seite
Für eine einfache Pause rufen Sie Thread.sleep() auf; dadurch wird der aktuelle Thread für die angegebene Dauer angehalten. Soll eine Aufgabe später oder wiederholt ausgeführt werden, während der aufrufende Thread weiterarbeiten kann, verwenden Sie einen ScheduledExecutorService. Die folgenden Beispiele zeigen beide Ansätze, den Umgang mit Unterbrechungen und das Aufräumen geplanter Aufgaben.
Das Anhalten der Ausführung gehört zur Dienstprogramm-Gruppe im Java-Tutorial, zusammen mit den übrigen Alltagsrezepten zu Datum, Zufall und Konsole.
Thread.sleep() für eine einfache blockierende Verzögerung verwenden
Thread.sleep() erwartet eine Dauer in Millisekunden und hält den aufrufenden Thread an. Dieses eigenständige Programm wartet eine Sekunde, bevor es seine Meldung ausgibt. Die main-Methode deklariert InterruptedException, sodass die Unterbrechung an den Aufrufer weitergegeben und nicht stillschweigend verworfen wird.
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread.sleep(1000);
System.out.println("One second has passed.");
}
}
Kann eine Methode InterruptedException nicht an ihren Aufrufer weitergeben, fangen Sie die Ausnahme ab und setzen den Unterbrechungsstatus mit Thread.currentThread().interrupt() wieder. Übergeordneter Code kann die Abbruchanforderung dann erkennen und entsprechend den Richtlinien der Anwendung behandeln. Ein Aufruf von sleep hält nur den aktuellen Thread an, nicht die anderen Threads des Prozesses.
TimeUnit.sleep() verwenden, um die Zeiteinheit anzugeben
TimeUnit.SECONDS.sleep(2) drückt eine Pause von zwei Sekunden direkt aus. Auch dieser Aufruf blockiert den aufrufenden Thread und kann unterbrochen werden. Wenden Sie daher dieselbe Strategie für Unterbrechungen an wie bei Thread.sleep().
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) {
try {
TimeUnit.SECONDS.sleep(2);
System.out.println("Two seconds have passed.");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.out.println("Pause interrupted.");
}
}
}
Wählen Sie diese Variante, wenn die Angabe der Zeiteinheit die Dauer verständlicher macht. TimeUnit.sleep() ist eine gut lesbare Möglichkeit, eine zeitlich begrenzte Wartezeit auszudrücken. Sie hält den aktuellen Thread jedoch nicht für andere Aufgaben verfügbar, während die Verzögerung verstreicht.
Eine wiederkehrende Aufgabe mit ScheduledExecutorService planen
Ein ScheduledExecutorService führt ein Runnable nach einer Verzögerung oder in regelmäßigen Abständen aus, während der aufrufende Thread verfügbar bleibt. scheduleAtFixedRate() erhält die Aufgabe, eine anfängliche Verzögerung, eine Periode und eine TimeUnit. Der Executor ruft die run()-Methode der Aufgabe auf; run() enthält die auszuführende Arbeit und plant die Aufgabe nicht selbst.
Dieses Programm startet eine Aufgabe nach einer Sekunde und fordert danach jede Sekunde eine weitere Ausführung an. Eine separate geplante Aktion bricht die wiederkehrende Aufgabe ab und fährt den Executor nach fünf Sekunden herunter. Die Planung hängt von den verfügbaren Laufzeitressourcen ab; daher können Anzahl und Zeitpunkt der ausgegebenen Zeilen variieren.
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) {
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
ScheduledFuture<?> task = executor.scheduleAtFixedRate(
() -> System.out.println("Task running"), 1, 1, TimeUnit.SECONDS);
executor.schedule(() -> {
task.cancel(false);
executor.shutdown();
}, 5, TimeUnit.SECONDS);
}
}
Behalten Sie das zurückgegebene ScheduledFuture, wenn die wiederkehrende Aufgabe möglicherweise abgebrochen werden muss. Fahren Sie einen Executor herunter, sobald die Anwendung ihn nicht mehr benötigt; andernfalls kann sein Arbeitsthread den Prozess am Beenden hindern. Für eine einzelne verzögerte Aktion verwenden Sie schedule() statt einer wiederkehrenden Planung.
Eine Methodenreferenz mit ScheduledExecutorService verwenden
Wenn eine vorhandene Methode ohne Argumente die Aufgabe darstellt, können Sie sie mit einer Methodenreferenz als Runnable übergeben. Dieses Programm plant einen einmaligen Aufruf in zwei Sekunden und fährt anschließend den Executor herunter. Beim Herunterfahren können keine neuen Aufgaben mehr eingereicht werden; bereits eingereihte Aufgaben dürfen jedoch noch abgeschlossen werden.
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) {
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.schedule(Main::executeTask, 2, TimeUnit.SECONDS);
executor.shutdown();
}
private static void executeTask() {
System.out.println("Task running");
}
}
Verwenden Sie eine Sleep-Methode für eine kurze Pause, wenn der aktuelle Thread dafür angehalten werden soll. Wählen Sie einen geplanten Executor, wenn andere Arbeit weiterlaufen soll oder eine Aufgabe später beziehungsweise wiederholt ausgeführt werden muss. Sleep blockiert den aufrufenden Thread und erfordert keine Bereinigung eines Executors. Geplante Arbeit lässt diesen Thread verfügbar, doch der Executor sollte heruntergefahren und wiederkehrende Aufgaben sollten abgebrochen werden, wenn sie nicht mehr benötigt werden.