1. Übersicht
Implementierung der Funktion der regelmäßigen Ausführung von Aufgaben in Java, hauptsächlich mit zwei Klassen, Timer- und Timertask -Klassen. Der Timer wird verwendet, um bestimmte Aufgaben in einem Hintergrund -Thread gemäß dem angegebenen Plan auszuführen.
TimerTask ist eine abstrakte Klasse, und ihre Unterklasse stellt eine Aufgabe dar, die von Timer geplant werden kann. Der spezifische zu ausgeführte Code ist in der Ausführungsmethode geschrieben, die TimerTask implementiert werden muss.
2. Schauen wir uns das einfachste Beispiel an
Lassen Sie es uns durch den Code erklären
importieren java.text.SimpledateFormat; import Java.util.date; import Java.util.timer; import Java.util.timertask; public Class TimerDemo {public static String getCurrenttime () {Datum = neuer Datum (); SimpleDateFormat SDF = new SimpledateFormat ("yyyy-mm-dd hh: mm: ss"); return sdf.format (Datum); } public static void main (String [] args) löst InterruptedException aus {System.out.println ("Hauptstart:"+getCurrentTime ()); startTimer (); Thread.Sleep (1000*5); // 5 Sekunden lang system.out.println schlafen ("Hauptende:"+getCurrentTime ()); } public static void startTimer () {timerTask task = new timerTask () {@Override public void run () {System.out.println ("Task run:"+getCurrentTime ()); }}; Timer Timer = new Timer (); Timer.Schedule (Aufgabe, 0); }}Um die Beobachtungsinformationen durch Drucken zu erleichtern, haben wir der Hauptmethode einige Druckinformationen hinzugefügt und als Thread bezeichnet. Darüber hinaus wird der Klasse eine GetCurrentTime -Methode hinzugefügt, um das aktuelle Datum zu erhalten.
Im obigen Code wird in der StartTimer -Methode ein Timertask -Objekt (die vom Timer ausgeführte Aufgabe) erstellt und ein Timer -Objekt erstellt, und die Zeitplanmethode der Timer -Klasse wird aufgerufen. Die Timer -Klasse verfügt über mehrere Zeitplanmethoden mit unterschiedlichen Parametern. Was hier verwendet wird, ist:
Öffentlicher Leerlaufplan (TimerTask -Aufgabe, lange Verzögerung)
Die Bedeutung dieser Methode besteht darin, die Aufgabenaufgabe auszuführen, nachdem der Timer die Zeit (Millisekunden) verzögert. Wenn die Verzögerung negativ oder 0 ist, wird die Aufgabe sofort ausgeführt. Und es handelt sich um eine einmalige Ausführungsaufgabe, und die Aufgabe wird anschließend nicht wiederholt (oder geplant).
Für die Timer -Klasse wird wie folgt auch eine Methode mit derselben Funktion bereitgestellt:
Öffentlicher Leerlaufplan (TimerTask -Aufgabe, Datumszeit)
Der Unterschied zwischen dieser Methode und der obigen Methode besteht darin, dass die obige Methode feststellt, dass die Ausführung für einen Zeitraum verzögert wird, und diese Methode gibt an, dass die Ausführung zu einem bestimmten Zeitpunkt durchgeführt wird. Beachten Sie, dass die Aufgabe sofort ausgeführt wird, wenn die aktuelle Zeit des Systems die durch die Parameterzeit angegebene Zeit überschritten hat.
Beim Ausführen des oben genannten Codes stellten wir fest, dass das Programm sofort zwei Informationen ausdruckt, ähnlich wie folgt:
Hauptstart: 2016-01-13 22:23:18
Aufgabelauf: 2016-01-13 22:23:18
Da der Wert des Verzögerungsparameters, den wir hier an die Zeitplanmethode übergeben, 0 beträgt, wird die Aufgabe sofort ausgeführt, sodass die Zeit zum Drucken der beiden Aussagen gleich ist, wie es sein sollte. Sie können den eingehenden Verzögerungswert selbst ändern, um die Änderungen in den Ausgabeinformationen anzuzeigen. Nach ca. 5 Sekunden (d. H. Die Schlafzeit) habe ich weiter 1 Nachricht gedruckt:
Hauptende: 2016-01-13 22:23:23
Die Zeit für das Drucken von Informationen liegt 5 Sekunden vor der obigen Anweisung, die mit der Schlafeinstellung übereinstimmt, was ebenfalls sehr vernünftig ist.
Aber wir werden ein sehr interessantes Phänomen finden, und wir werden feststellen, dass der Prozess nicht verlassen wird. Zu diesem Zeitpunkt ist der Hauptfaden beendet. Dies bedeutet, dass nach Abschluss des Timers die Aufgabe abgeschlossen ist. Auch wenn keine Aufgaben darauf warten, später ausgeführt zu werden, wird der im Timer erstellte Hintergrund -Thread nicht sofort beendet. Ich habe die relevante Java -Dokument -Dokumentation überprüft und erklärt, dass der Timer -Thread nicht aktiv beendet wird und auf die Müllsammlung warten muss, aber die Müllsammlung von Java kann nicht vom Code selbst gesteuert werden, sondern wird von der virtuellen Maschine gesteuert.
Nach der Forschung wurde festgestellt, dass beim Erstellen eines Timer -Objekts und der Ausführung des Timer Timer = New Timer (); Anweisung, der Timer -Thread wird erstellt. Mit anderen Worten, auch wenn der obige Code den Timer.Schedule (Aufgabe, 0) nicht hat; Aussage, das Programm wird nicht beenden. Ich finde das ziemlich unangemessen. Ich habe den Quellcode der Timer -Klasse erneut untersucht und festgestellt, dass er auch einen Konstruktor mit booleschen Parametern hat:
öffentlicher Timer (Boolean Isdaemon)
Wie Sie aus dem Parameternamen sehen können, ist der von Timer erstellte Timer -Thread, wenn der Parameterwert stimmt, der Daemon -Thread. Die Bedeutung eines Daemon -Threads lautet: Wenn alle Worker -Threads in der Java -Prozessprozesse beenden, wird der Daemon -Thread automatisch beendet.
Zu diesem Zeitpunkt müssen wir nur den Code ändern, um das Timer -Objekt im obigen Beispiel zu erstellen: Timer Timer = New Timer (True);
Nachdem Sie festgestellt haben, dass das Programm ausgeführt wird, wird das Programm nach dem Haupt -Thread beendet (der Haupt -Thread ist kein Daemon -Thread, sondern ein Worker -Thread), was bedeutet, dass der Timer -Thread auch beendet, was bedeutet, dass nach dem Hinzufügen des Parameters der erstellte Daemon -Thread der Daemon -Thread ist.
Das Problem ist jedoch, dass in realen Anwendungsszenarien viele Arbeiter -Threads ausgeführt werden und das Programm nicht beiläufig beendet. Was ist also, wenn der Timer sofort ausgeht oder schließt? Wir werden dies unten vorstellen.
3. Ausgang des Timers
Die Timer -Klasse bietet eine Abbrechen -Methode, um den Timer abzubrechen. Das Aufrufen der Abbrechen -Methode beendet diesen Timer und verwerfen alle derzeit geplanten Aufgaben. Dies stört die aktuell ausführende Aufgabe nicht (falls vorhanden). Sobald der Timer beendet ist, wird auch sein Ausführungs -Thread beendet, und es können nicht mehr Aufgaben geplant werden.
Beachten Sie, dass Sie durch Aufrufen dieser Methode innerhalb der Run -Methode der Timer -Aufgabe, die diesen Timer bezeichnet, unbedingt sicherstellen können, dass die ausgeführte Aufgabe die letzte von diesem Timer ausgeführte Aufgabe ist. Diese Methode kann wiederholt aufgerufen werden; Die zweite und nachfolgende Anrufe sind jedoch ungültig.
Schauen wir uns einen anderen Beispielcode an:
importieren java.text.SimpledateFormat; import Java.util.date; import Java.util.timer; import Java.util.timertask; public Class TimerDemo {public static String getCurrenttime () {Datum = neuer Datum (); SimpleDateFormat SDF = new SimpledateFormat ("yyyy-mm-dd hh: mm: ss"); return sdf.format (Datum); } public static void main (String [] args) löst InterruptedException aus {System.out.println ("Hauptstart:"+getCurrentTime ()); Timer Timer = startTimer (); Thread.Sleep (1000*5); // 5 Sekunden lang system.out.println schlafen ("Hauptende:"+getCurrentTime ()); timer.cancel (); } public static Timer startTimer () {timerTask task = new timerTask () {@Override public void run () {System.out.println ("Task run:"+getCurrentTime ()); }}; Timer Timer = new Timer (); Timer.Schedule (Aufgabe, 0); Return Timer; }} Das Ausführen des Programms entspricht genau der Ausgabe des obigen Beispiels. Der Unterschied besteht darin, dass die Hauptmethode endet. Der Prozess wird aktiv beendet, was bedeutet, dass der Timer -Thread geschlossen wurde.
Weil wir die Abbrechen -Methode in der Hauptmethode aufrufen. Beachten Sie, dass Sie sicherstellen, dass die Aufgabe, die Sie ausführen möchten, gestartet oder abgeschlossen ist, wenn die Aufgabe nicht ausgeführt wurde. Rufen Sie einfach Cancel an und alle Aufgaben werden nicht ausgeführt. Zum Beispiel der obige Code,
Wenn wir beispielsweise im obigen Code die Abbrechen -Methode in der Hauptmethode nicht aufrufen, sondern den Timer.Schedule (Aufgabe, 0) hinzufügen; Anweisung in der StartTimer -Methode und fügen Sie den Timer.Cancel () hinzu; Nach dem Ausführen werden Sie feststellen, dass die Timer -Aufgabe nicht ausgeführt wird, da sie vor Abschluss der Ausführung storniert wird.
4. Ausführen regelmäßig Aufgaben ausführen
Im obigen Beispiel stellen wir eine einmalige Aufgabe ein, dh die Zeit des Timers ist gekommen. Nachdem die Aufgabe ausgeführt wurde, wird sie später nicht wiederholt. In den tatsächlichen Anwendungen gibt es viele Szenarien, in denen die gleiche Aufgabe wiederholt regelmäßig ausgeführt werden muss. Es gibt zwei Situationen: Eine besteht darin, von Zeit zu Zeit Aufgaben auszuführen, und der andere ist es, jeden Tag (oder wöchentlich, monatlich usw.) Aufgaben zu einem bestimmten (oder mehreren) Zeitpunkten auszuführen.
Schauen wir uns zunächst den ersten Fall an, der alle 10 Sekunden die gleiche Aufgabe ausführen kann. Der Code ist wie folgt:
importieren java.text.SimpledateFormat; import Java.util.date; import Java.util.timer; import Java.util.timertask; public Class TimerDemo {public static String getCurrenttime () {Datum = neuer Datum (); SimpleDateFormat SDF = new SimpledateFormat ("yyyy-mm-dd hh: mm: ss"); return sdf.format (Datum); } public static void main (String [] args) löst InterruptedException aus {System.out.println ("Hauptstart:"+getCurrentTime ()); startTimer (); } public static void startTimer () {timerTask task = new timerTask () {@Override public void run () {System.out.println ("Task run:"+getCurrentTime ()); try {thread.sleep (1000*3); } catch (interruptedException e) {e.printstacktrace (); }}}; Timer Timer = new Timer (); Timer.Schedule (Aufgabe, 1000*5,1000*10); }} Führen Sie das obige Programm aus und die Ausgabeinformationen lautet wie folgt (da der Timer nicht stoppt und die Aufgabe wiederholt wird, wird die Ausgabe kontinuierlich ausgegeben. Nur einige der vorherigen Ausgänge werden hier kopiert)
Hauptstart: 2016-01-14 08:41:14
Aufgabelauf: 2016-01-14 08:41:19
Aufgabelauf: 2016-01-14 08:41:29
Aufgabelauf: 2016-01-14 08:41:39
Aufgabelauf: 2016-01-14 08:41:49
Aufgabelauf: 2016-01-14 08:42:00
Aufgabelauf: 2016-01-14 08:42:10
Aufgabelauf: 2016-01-14 08:42:20
Aufgabelauf: 2016-01-14 08:42:30
Aufgabelauf: 2016-01-14 08:42:40
Im obigen Code nennen wir Timer.Schedule (Aufgabe 1000*5,1000*10); Dies bedeutet, dass die Aufgabe um 5 Sekunden verzögert wird und dann alle 10 Sekunden wiederholt wird. Wir beobachten, dass die Druckzeit in den Ausgangsinformationen wie erwartet übereinstimmt. Darüber hinaus ist ersichtlich, dass das Intervall basierend auf der Startzeit für Aufgaben berechnet wird, dh nach Abschluss der Aufgabe nicht weitere 10 Sekunden warten.
Die Timer -Klasse verfügt über zwei Methoden, um solche Funktionen zu implementieren, wie folgt:
öffentlicher Leerlaufplan (TimerTask -Aufgabe, lange Verzögerung, langer Zeitraum) öffentlicher Leerplan (TimerTask -Aufgabe, Datum zum ersten Mal, langer Zeitraum)
Die erste Methode, die wir oben Code verwenden. Der Unterschied zwischen den beiden Methoden ist die Zeit der ersten Ausführung. Die erste Methode wird nach einer bestimmten Verzögerung eines Zeitraums (in Millisekunden) ausgeführt. Die zweite Methode wird zu einem bestimmten Zeitpunkt ausgeführt.
Zu diesem Zeitpunkt betrachten wir das folgende Szenario. Wenn die Ausführungszeit einer Aufgabe die nächste Wartezeit überschreitet, was wird dann passieren? Schauen wir es uns durch den Code an:
importieren java.text.SimpledateFormat; import Java.util.date; import Java.util.timer; import Java.util.timertask; public Class TimerDemo {public static String getCurrenttime () {Datum = neuer Datum (); SimpleDateFormat SDF = new SimpledateFormat ("yyyy-mm-dd hh: mm: ss"); return sdf.format (Datum); } public static void main (String [] args) löst InterruptedException aus {System.out.println ("Hauptstart:"+getCurrentTime ()); startTimer (); } public static void startTimer () {timerTask task = new timerTask () {@Override public void run () {System.out.println ("Task begin:"+getCurrentTime ()); try {thread.sleep (1000*10); } catch (interruptedException e) {e.printstacktrace (); } System.out.println ("Taskend:"+getCurrentTime ()); }}; Timer Timer = new Timer (); Timer.Schedule (Aufgabe, 1000*5,1000*5); }} Im Vergleich zum vorherigen Code haben wir nur 2 Codes geändert und den Druck geändert. Einer besteht darin, den Schlaf in der Laufmethode auf 10 Sekunden zu ändern, und das andere ist, den Ausführungszyklus der Aufgabe auf 5 Sekunden zu ändern. Mit anderen Worten, die Ausführungszeit der Aufgabe übersteigt das Intervall zwischen der wiederholten Ausführung der Aufgabe. Führen Sie das Programm aus, die vorherige Ausgabe lautet wie folgt:
Hauptstart: 2016-01-14 09:03:51
Aufgabe Beginn: 2016-01-14 09:03:56
Aufgabe Ende: 2016-01-14 09:04:06
Aufgabe Beginn: 2016-01-14 09:04:06
Aufgabe Ende: 2016-01-14 09:04:16
Aufgabe Beginn: 2016-01-14 09:04:16
Aufgabe Ende: 2016-01-14 09:04:26
Aufgabe Beginn: 2016-01-14 09:04:26
Aufgabe Ende: 2016-01-14 09:04:36
Aufgabe Beginn: 2016-01-14 09:04:36
Aufgabe Ende: 2016-01-14 09:04:46
Aufgabe Beginn: 2016-01-14 09:04:46
Aufgabe Ende: 2016-01-14 09:04:56
Es ist ersichtlich, dass nach jeder Aufgabe die nächste Aufgabe sofort ausgeführt wird. Da die Zeit, die vom Beginn der Aufgabe bis zum Abschluss der Aufgabe genommen wurde, das Intervall zwischen der Wiederholung der Aufgaben überschritten hat, wird die Ausführung wiederholt.
5. Aufgaben regelmäßig ausführen (wiederholen Sie den festen Zeitpunkt)
Lassen Sie uns eine solche Funktion implementieren und jeden Tag um 1 Uhr morgens regelmäßig eine Aufgabe ausführen, die diese Funktion in vielen Systemen hat, z. B. zeitaufwändige und ressourcenverbrauchende Aufgaben wie Datensicherung und Datenstatistik in dieser Aufgabe. Der Code ist wie folgt:
importieren java.text.SimpledateFormat; import Java.util.calendar; import Java.util.date; Import Java.util.timer; import Java.util.timerTask; öffentliche Klassen -TimerDemo {öffentliche statische String GetCurentTime () {Date datum = new Date (); SimpleDateFormat SDF = new SimpledateFormat ("yyyy-mm-dd hh: mm: ss"); return sdf.format (Datum); } public static void main (String [] args) löst InterruptedException aus {System.out.println ("Hauptstart:" + getCurrentTime ()); startTimer (); } public static void startTimer () {timerTask task = new timerTask () {@Override public void run () {System.out.println ("Task begin:" + getCurrentTime ()); try {thread.sleep (1000 * 20); } catch (interruptedException e) {e.printstacktrace (); } System.out.println ("Taskend:" + getCurrentTime ()); }}; Timer Timer = new Timer (); Timer.Schedule (Aufgabe, BuildTime (), 1000 * 60 * 60 * 24); } private statische Datum BuildTime () {Calendar Calendar = Calendar.getInstance (); Calendar.set (Calendar.hour_of_day, 1); Calendar.set (Calendar.minute, 0); Calendar.set (Calendar.second, 0); Datum Uhrzeit = calendar.getTime (); if (time.before (neues Datum ())) {// Wenn die aktuelle Zeit nach 1 Uhr morgens liegt, wird 1 Tag benötigt, andernfalls wird die Aufgabe sofort ausgeführt. // Viele Systeme müssen häufig Aufgaben sofort ausführen, wenn das System beginnt, aber sie müssen sie jeden Tag um 1 Uhr morgens ausführen. Was soll ich tun? // Es ist sehr einfach. Führen Sie die Aufgabe einfach separat aus, wenn das System den Anruf initialisiert (kein Timer wird benötigt. Es ist nur der Code, um diese Aufgabe auszuführen) Zeit = Addday (Zeit, 1). } Rücklaufzeit; } privates statisches Datum addday (Datum Datum, int Tage) {Kalender startdt = calendar.getInstance (); startdt.settime (Datum); startdt.add (Calendar.day_of_month, Tage); return startdt.getTime (); }}Da es in Intervallen von 24 Stunden ausgeführt wird, ist es unmöglich, auf die Beobachtung der Ausgabe zu warten.
6. Zusammenfassung
In diesem Artikel wird der Mechanismus eingeführt, wie zeitgesteuerte Aufgaben mithilfe der Java -Timer -Klasse ausgeführt werden können. Es ist zu erkennen, dass es noch viele Möglichkeiten gibt, auf die man achten kann. In den in diesem Artikel eingeführten Beispiele entspricht jeder Timer nur einer Aufgabe.
Der in diesem Artikel eingeführte Inhalt kann die meisten Anwendungsszenarien erfüllen, aber es gibt immer noch einige Probleme, z. B. mehrere Aufgaben für einen Timer einbeziehen? Kann ich wieder Aufgaben hinzufügen, nachdem der Timer abgesagt wurde? Welche anderen Methoden sind in der Timer -Klasse verfügbar? Diese Fragen werden im folgenden Blog -Beitrag eingeführt.
Original -Link: http://www.cnblogs.com/51kata/p/5128745.html
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, es wird für das Lernen aller hilfreich sein und ich hoffe, jeder wird Wulin.com mehr unterstützen.