Wie plane ich die Ausführung einer Aufgabe in regelmäßigen Abständen?

76

Ich habe einige Codes ausprobiert, um eine geplante Aufgabe zu implementieren, und mir diese Codes ausgedacht.

import java.util.*;

class Task extends TimerTask {


    int count = 1;

    // run is a abstract method that defines task performed at scheduled time.
    public void run() {
        System.out.println(count+" : Mahendra Singh");
        count++;
    }
}

class TaskScheduling {

   public static void main(String[] args) {
       Timer timer = new Timer();


       // Schedule to run after every 3 second(3000 millisecond)
       timer.schedule( new Task(), 3000);   
   }
}

Meine Ausgabe:

1  :  Mahendra Singh

Ich hatte erwartet, dass der Compiler eine Reihe von Mahendra Singh in regelmäßigen Abständen von 3 s druckt, aber obwohl ich ungefähr 15 Minuten gewartet habe, erhalte ich nur eine Ausgabe ... Wie löse ich das?

Manish Basdeo
quelle
Quartz Scheduler , um Hilfe Java - Anwendung eines Job / Task - Planer zu einem bestimmten Datum und Uhrzeit läuft Check voll Beispiel dafür
Tell Me How
1
Diese Klassen wurden durch das Executors-Framework ersetzt . Siehe den 7. Absatz im JavaDoc für Timer.
Basil Bourque

Antworten:

77

Verwenden timer.scheduleAtFixedRate

public void scheduleAtFixedRate(TimerTask task,
                                long delay,
                                long period)

Plant die angegebene Aufgabe für die wiederholte Ausführung mit fester Rate, beginnend nach der angegebenen Verzögerung. Nachfolgende Ausführungen finden in ungefähr regelmäßigen Abständen statt, getrennt durch den angegebenen Zeitraum.
Bei der Ausführung mit fester Rate wird jede Ausführung relativ zur geplanten Ausführungszeit der anfänglichen Ausführung geplant. Wenn eine Ausführung aus irgendeinem Grund verzögert wird (z. B. durch Speicherbereinigung oder andere Hintergrundaktivitäten), werden zwei oder mehr Ausführungen schnell hintereinander ausgeführt, um "aufzuholen". Auf lange Sicht ist die Häufigkeit der Ausführung genau der Kehrwert des angegebenen Zeitraums (vorausgesetzt, die Systemuhr, die Object.wait (long) zugrunde liegt, ist korrekt).

Die Ausführung mit fester Rate eignet sich für wiederkehrende Aktivitäten, die von der absoluten Zeit abhängig sind, z. B. das stündliche Klingeln eines Glockenspiels oder das tägliche Ausführen geplanter Wartungsarbeiten zu einer bestimmten Zeit. Es ist auch für wiederkehrende Aktivitäten geeignet, bei denen die Gesamtzeit für die Ausführung einer festen Anzahl von Ausführungen wichtig ist, z. B. ein Countdown-Timer, der zehn Sekunden lang einmal pro Sekunde tickt. Schließlich ist die Ausführung mit fester Rate geeignet, um mehrere sich wiederholende Zeitgeberaufgaben zu planen, die in Bezug zueinander synchronisiert bleiben müssen.

Parameter:

  • Aufgabe - Aufgabe, die geplant werden soll.
  • Verzögerung - Verzögerung in Millisekunden, bevor die Aufgabe ausgeführt werden soll.
  • Zeitraum - Zeit in Millisekunden zwischen aufeinanderfolgenden Aufgabenausführungen.

Würfe:

  • IllegalArgumentException - Wenn die Verzögerung negativ ist oder die Verzögerung + System.currentTimeMillis () negativ ist.
  • IllegalStateException - Wenn die Aufgabe bereits geplant oder abgebrochen wurde, wurde der Timer abgebrochen oder der Timer-Thread beendet.
st0le
quelle
4
ScheduleAtFixedRate behebt sein Problem, die Ausgabe nur einmal zu erhalten, nicht.
James AN Stauffer
1
@ JamesA.N.Stauffer, er braucht die Ausgabe wiederholt, nicht einmal.
st0le
3
Ja, aber die Wiederholung wird einfach durch Hinzufügen eines dritten Arguments erreicht - eine Änderung der Methode ist nicht erforderlich.
James AN Stauffer
2
@ st0le. Betrachten Sie die folgende Analogie. Der Fragesteller sagt "Der Himmel ist blau". Sie sagen "Nein, das Gras ist grün." - Ihre Antwort wäre ideal, wenn seine Frage "Was ist eine Wiederholung mit fester Rate?" Lautete.
Tony9099
Was ist, wenn Sie möchten, dass es sich um eine zufällige Rate innerhalb bestimmter Ober- und Untergrenzen handelt?
Hack-R
80

Vorteil von ScheduledExecutorServiceüberTimer

Ich möchte Ihnen eine Alternative zur TimerVerwendung von ScheduledThreadPoolExecutor anbieten , einer Implementierung der ScheduledExecutorService- Schnittstelle. Laut "Java in Concurrency" hat es einige Vorteile gegenüber der Timer-Klasse:

A Timererstellt nur einen einzigen Thread zum Ausführen von Timer-Aufgaben. Wenn die Ausführung einer Timer-Task zu lange dauert, kann die Timing-Genauigkeit anderer TimerTaskbeeinträchtigt werden. Wenn geplant ist, dass eine wiederkehrende TimerTaskAufgabe alle 10 ms ausgeführt wird und eine andere Timer-Task 40 ms benötigt, wird die wiederkehrende Aufgabe entweder (abhängig davon, ob sie mit fester Rate oder fester Verzögerung geplant wurde) nach der langen viermal viermal hintereinander aufgerufen. Das Ausführen der Aufgabe wird abgeschlossen oder "verfehlt" vier Aufrufe vollständig. Geplante Thread-Pools beheben diese Einschränkung, indem Sie mehrere Threads für die Ausführung von verzögerten und periodischen Aufgaben bereitstellen können.

Ein weiteres Problem mit Timer ist, dass es sich schlecht verhält, wenn a TimerTask eine ungeprüfte Ausnahme auslöst . Wird auch als "Fadenleckage" bezeichnet.

Der Timer-Thread fängt die Ausnahme nicht ab, daher beendet eine nicht aktivierte Ausnahme, die von a ausgelöst wird TimerTask, den Timer-Thread. Der Timer lässt den Thread in dieser Situation auch nicht wieder auferstehen. Stattdessen wird fälschlicherweise davon ausgegangen, dass der gesamte Timer abgebrochen wurde. In diesem Fall werden TimerTasks, die bereits geplant, aber noch nicht ausgeführt wurden, nie ausgeführt, und neue Aufgaben können nicht geplant werden.

Eine weitere Empfehlung: Wenn Sie Ihren eigenen Planungsdienst erstellen müssen, können Sie die Bibliothek möglicherweise weiterhin nutzen, indem Sie DelayQueueeine BlockingQueueImplementierung verwenden, die die Planungsfunktionalität von bereitstellt ScheduledThreadPoolExecutor. A DelayQueueverwaltet eine Sammlung verzögerter Objekte. Mit einer Verzögerung ist eine Verzögerungszeit verbunden: Mit dieser DelayQueueOption können Sie ein Element nur dann übernehmen, wenn seine Verzögerung abgelaufen ist. Objekte werden nach DelayQueueder mit ihrer Verzögerung verbundenen Zeit von einer Bestellung zurückgegeben.

Alexandr
quelle
4
Ein weiteres Problem mit dem Timer ist, dass er beim Ändern der Systemuhr den Timer
durcheinander bringt
15
public void schedule(TimerTask task,long delay)

Plant die angegebene Aufgabe für die Ausführung nach der angegebenen Verzögerung.

Sie wollen:

public void schedule(TimerTask task, long delay, long period)

Plant die angegebene Aufgabe für die wiederholte Ausführung mit fester Verzögerung , beginnend nach der angegebenen Verzögerung. Nachfolgende Ausführungen finden in ungefähr regelmäßigen Abständen statt, die durch den angegebenen Zeitraum getrennt sind.

Yurib
quelle
2
timer.scheduleAtFixedRate( new Task(), 1000,3000); 
Brijesh
quelle