Wenn wir während unseres Programmierungsprozesses einige einfache Zeitaufgaben ausführen müssen, müssen wir keine komplexe Kontrolle durchführen. Wir können in Betracht ziehen, Timer -Timing -Aufgaben in JDK zu verwenden, um dies zu erreichen. Die folgende LZ analysiert den Java -Timer -Timer basierend auf seinem Prinzip, Beispiel und Timerdefekt.
1. Einführung
In Java muss eine vollständige Timing -Aufgabe vom Timer- und TimerTask -Klassen erledigt werden. So werden sie in der API definiert. Timer: Ein Werkzeug, mit dem Aufgaben anordnen, die Threads später in Hintergrund -Threads ausführen. Aufgaben können einmal ausgeführt oder wiederholt ausgeführt werden. Aufgabe von Timertask: Timer als Aufgabe geplant, die ausgeführt oder wiederholt wird. Wir können verstehen, dass Timer ein Timer -Tool ist, mit dem bestimmte Aufgaben in einem Hintergrund -Thread ausgeführt werden sollen, und TimerTask eine abstrakte Klasse, deren Unterklasse eine Aufgabe darstellt, die von Timer geplant werden kann.
Timer -Klasse <BR /> Im Werkzeugklassen -Timer werden vier Konstruktormethoden bereitgestellt. Jeder Konstruktor startet einen Timer -Thread. Gleichzeitig kann die Timer-Klasse sicherstellen, dass mehrere Threads ein einzelnes Timer-Objekt ohne externe Synchronisation freigeben können, sodass die Timer-Klasse Thread-Safe ist. Da jedoch jedes Timer -Objekt einem einzelnen Hintergrund -Thread entspricht, mit dem alle Timeraufgaben nacheinander ausgeführt werden, sollte die Zeit für die Ausführung unserer Thread -Aufgabe im Allgemeinen sehr kurz sein. Aufgrund besonderer Umstände ist die Ausführungszeit einer bestimmten Timer -Aufgabe jedoch zu lang, sodass sie den Timer -Task -Ausführungs -Thread "ausschließlich" und alle nachfolgenden Threads warten müssen, bis er ausgeführt wird, was die Ausführung nachfolgender Aufgaben verzögert und diese Aufgaben zusammenhüpfen lassen. Wir werden die spezifische Situation später analysieren.
Wenn das Programm den Timer initialisiert, wird die Timing -Aufgabe entsprechend der festgelegten Zeit ausgeführt. Timer bietet die Zeitplanmethode mit mehreren Überladungen zur Anpassung an verschiedene Situationen wie folgt:
Zeitplan (TimerTask -Aufgabe, Datumszeit): Planen Sie die Ausführung der angegebenen Aufgabe zum angegebenen Zeitpunkt.
Zeitplan (TimerTask -Aufgabe, Datum zum ersten Mal, langer Zeitraum): Planen Sie die angegebene Aufgabe, um die wiederholte Ausführung der festen Verzögerung zum angegebenen Zeitpunkt zu starten.
Zeitplan (TimerTask -Aufgabe, lange Verzögerung): Planen Sie die angegebene Aufgabe, die nach der angegebenen Verzögerung ausgeführt werden soll.
Zeitplan (TimerTask -Aufgabe, lange Verzögerung, langer Zeitraum): Planen Sie die angegebene Aufgabe, die nach der angegebenen Verzögerung wiederholt verzögert wird.
Gleichzeitig wird die ScheduleatFixedRate -Methode ebenfalls überladen. Die ScheduleatFixedrat -Methode entspricht dem Zeitplan, aber ihr Fokus ist unterschiedlich und der Unterschied wird später analysiert.
ScheduleatFixedRate (TimerTask -Aufgabe, Datum des ersten Mals, langer Zeitraum): Planen Sie die angegebene Aufgabe, die zu einem bestimmten Zeitpunkt wiederholt zu einem festgelegten Preis ausgeführt werden soll.
ScheduleatFixedRate (TimerTask-Aufgabe, lange Verzögerung, langer Zeitraum): Planen Sie die angegebene Aufgabe, um nach der angegebenen Verzögerung wiederholte Ausführung mit fester Rate zu starten.
TIMERTask
Die TimerTask -Klasse ist eine abstrakte Klasse, die von Timer als Aufgabe arrangiert oder wiederholt wird. Es verfügt über eine abstrakte Methode Run () -Methode, mit der die von der entsprechenden Timer -Aufgabe ausgeführten Operationen durchgeführt werden sollen. Daher muss jede bestimmte Aufgabenklasse Timertask erben und dann die Run () -Methode überschreiben.
Darüber hinaus verfügt es über zwei nicht abstrakte Methoden:
Boolean Cancel (): Abbrechen Sie diese Timer -Aufgabe.
Long plhoedexecutiontime (): Gibt die geplante Ausführungszeit der neuesten tatsächlichen Ausführung dieser Aufgabe zurück.
2. Beispiele
2.1. Geben Sie die Verzögerungszeit für die Ausführung von Zeitaufgaben an
public class timertest01 {timer timer; public timertest01 (int time) {timer = new Timer (); Timer.Schedule (neuer Timertaskest01 (), Zeit * 1000); } public static void main (String [] args) {System.out.println ("Timer begin ..."); neuer TICEERTEST01 (3); }} public class timertaskest01 erweitert Timertask {public void run () {System.out.println ("Zeit ist up !!!"); }} Auslaufergebnisse:
Erster Druck: Timer beginnen ...
Drucken in 3 Sekunden: Zeit ist hoch !!!
2.2. Führen Sie die Zeitaufgaben zum bestimmten Zeitpunkt aus
public class timertest02 {timer timer; public timertest02 () {Datum Uhrzeit = Gettime (); System.out.println ("Zeitpunkt Zeitpunkt" + Zeit); Timer = neuer Timer (); Timer.Schedule (neuer Timertaskest02 (), Zeit); } public date GetTime () {Calendar calendar = calendar.getInstance (); Calendar.set (Calendar.hour_of_day, 11); Calendar.set (Calendar.minute, 39); Calendar.set (Calendar.second, 00); Datum Uhrzeit = calendar.getTime (); Rücklaufzeit; } public static void main (String [] args) {new timertest02 (); }} public class timertaskest02 erweitert Timertask {@Override public void run () {System.out.println ("Threadaufgaben zur bestimmten Zeit ausführen ..."); }} Wenn die Zeit um 11:39:00 Uhr erreicht ist, wird die Thread -Aufgabe natürlich ausgeführt, sie wird ausgeführt, auch wenn sie größer ist als in dieser Zeit! ! Das Ausführungsergebnis ist:
Angegebene Zeitzeit = Di 10. Juni 11:39:00 CST 2014
Threadaufgaben zur bestimmten Zeit ausführen ...
2.3. Nach der Verzögerung der angegebenen Zeit wird die Zeitaufgabe in der angegebenen Intervallzeit ausgeführt.
public class timertest03 {timer timer; public timertest03 () {timer = new Timer (); Timer.Schedule (neuer Timertaskest03 (), 1000, 2000); } public static void main (String [] args) {new timertest03 (); }} public class timertaskest03 erweitert TimerTask {@Override public void run () {Datum date = neues Datum (this.ScheduledexecutionTime ()); System.out.println ("Die Zeit für die Ausführung dieses Threads ist:" + Datum); }} Auslaufergebnisse:
Die Zeit für die Ausführung dieses Threads ist: Di 10. Juni 21:19:47 CST 2014
Die Zeit für die Ausführung dieses Threads ist: Di 10. Juni 21:19:49 CST 2014
Die Zeit für die Ausführung dieses Threads ist: Di 10. Juni 21:19:51 CST 2014
Die Zeit für die Ausführung dieses Threads ist: Di 10. Juni 21:19:53 CST 2014
Die Zeit für die Ausführung dieses Threads ist: Di 10. Juni 21:19:55 CST 2014
Die Zeit für die Ausführung dieses Threads ist: Di 10. Juni 21:19:57 CST 2014
................
Für diese Thread -Aufgabe wird sie die Aufgabe nicht beenden, es wird weiter ausgeführt.
Für die oben genannten Beispiele hat LZ es nur kurz demonstriert und das Beispiel der ScheduleatFixedrate -Methode nicht erklärt. Tatsächlich entspricht diese Methode mit der Zeitplanmethode!
2.4. Analysieren Sie den Zeitplan und ScheduleatFixedrate
1), Zeitplan (TimerTask -Aufgabe, Datumszeit), Zeitplan (TimerTask -Aufgabe, lange Verzögerung)
Bei beiden Methoden wird die Aufgabe sofort ausgeführt. Scheduledexecutiontime ändert sich aufgrund einer übermäßigen Ausführung einer Aufgabe nicht.
2) Zeitplan (TimerTask -Aufgabe, Datum Erstmal, langer Zeitraum), Zeitplan (TimeTask -Aufgabe, lange Verzögerung, langer Zeitraum)
Diese beiden Methoden unterscheiden sich etwas von den oben genannten zwei. Wie bereits erwähnt, wird die Timer -Timer -Aufgabe verzögert, da die vorherige Aufgabe lange ausgeführt wird. In diesen beiden Methoden ändert sich die geplante Zeit jeder ausgeführten Aufgabe mit der tatsächlichen Zeit der vorherigen Aufgabe, dh enderExecutiontime (n+1) = Reexecutiontime (n)+Periode. Das heißt, wenn die n -te Aufgabe diesen Ausführungszeitprozess aufgrund einer Situation und schließlich SystemcurrentTime> = teplaneDexecutiontime (N+1) verursacht, ist dies die N+1 -Aufgabe und wird aufgrund der Zeit nicht ausgeführt. Es wird darauf warten, dass die n -te Aufgabe vor der Ausführung ausgeführt wird, und dies führt zwangsläufig zur Veröffentlichung und Änderung der N -+2 -Ausführung implementiert, dh plantexecutiontime (n+2) = ReefePeaseCutiontime (N+1)+Zeitzeit. Daher achten diese beiden Methoden mehr auf die Stabilität der Speicherintervallzeit.
3) ScheduleatFixedRate (TimerTask -Aufgabe, Datum des ersten Zeitpunkts, langer Zeitraum), ScheduleatFixedrate (TimerTask -Aufgabe, lange Verzögerung, langer Zeitraum)
Wie bereits erwähnt, ist der Schwerpunkt von ScheduleatFixedrate- und Zeitplanmethoden unterschiedlich. Die Zeitplanmethode konzentriert sich auf die Stabilität der Sparenintervallzeit, während sich die ScheduleatFixedrate -Methode mehr auf die Aufrechterhaltung der Stabilität der Ausführungsfrequenz konzentriert. Warum sagst du das, die Gründe sind wie folgt. In der Zeitplanmethode führt die Verzögerung der vorherigen Aufgabe zu einer Verzögerung der Zeitverzögerung, während die ScheduleatFixedRate -Methode nicht der Fall ist. Wenn die Ausführungszeit der n -ten Aufgabe zu lang ist, wird das SystemcurrentTime> = ungedExecutiontime (N+1) nicht darauf warten, dass die N+1 -Aufgabe sofort ausgeführt wird. Daher unterscheidet sich die Berechnungsmethode der Ausführungszeit der ScheduleatFixedrat -Methode vom Zeitplan, jedoch plantexecutiontime (n) = firstExecUTetime +n*Periodenzeit, und die Berechnungsmethode bleibt für immer unverändert. Daher konzentriert sich ScheduleatFixedRate mehr darauf, die Ausführungsfrequenz stabil zu halten.
3. Timer -Defekte
3.1. Timerfehler
Der Timer -Timer kann zeitlich Zeit (Aufgaben zum bestimmten Zeitpunkt ausführen), Verzögerungsaufgaben (5 Sekunden) und regelmäßig Aufgaben ausführen (Aufgaben bei 1 Sekunde ausführen), aber der Timer hat einige Mängel. Erstens basiert die Unterstützung von Timer für die Planung auf der absoluten Zeit und nicht auf der relativen Zeit. Daher ist es sehr empfindlich gegenüber Änderungen der Systemzeit. Zweitens fängt der Timer -Thread keine Ausnahmen auf. Wenn die nicht überprüfte Ausnahme von Timertask ausgelöst wird, wird der Timer -Thread beendet. Gleichzeitig wird der Timer die Ausführung des Threads nicht fortsetzen und fälschlicherweise glauben, dass der gesamte Timer -Thread storniert wird. Gleichzeitig wird TimerTask, das für noch nicht ausgeführt wurde, nicht mehr ausgeführt, und es können nicht neue Aufgaben geplant werden. Wenn TimerTask eine ungeprüfte Ausnahme ausgelegt hat, erzeugt der Timer unvorhersehbares Verhalten.
1) Timer -Verwaltungszeitverzögerungsfehler <BR /> Der vorherige Timer erstellt nur eine Thread -Aufgabe, wenn eine zeitgesteuerte Aufgabe ausgeführt wird. Wenn es mehrere Threads gibt, wenn einer der Threads aus irgendeinem Grund zu lange zu lange ist und das Intervall zwischen den beiden Aufgaben die Zeit zwischen ihnen überschreitet, treten einige Defekte auf:
public class timertest04 {privater Timer -Timer; öffentlicher langer Start; public timertest04 () {this.Timer = new Timer (); start = system.currentTimemillis (); } public void timerOne(){ timer.schedule(new TimerTask() { public void run() { System.out.println("timerOne invoked ,the time:" + (System.currentTimeMillis() - start)); try { Thread.sleep(4000); //Thread sleeps 3000 } catch (InterruptedException e) { e.printStackTrace(); } }}}, 1000); } public void timerTwo () {timer.Schedule (new Timertask () {public void run () {System.out.println ("Timerone aufgerufen, die Zeit:" + (System.CurrentTimemillis () - Start);}}, 3000); } public static void main (String [] args) löst eine Ausnahme aus {timertest04 test = new timertest04 (); test.timerone (); test.timertwo (); }} Nach unserem normalen Denken sollte Timertwo nach 3s ausgeführt werden, und das Ergebnis sollte sein:
Timerone aufgerufen, die Zeit: 1001
Timerone aufgerufen, die Zeit: 3001
Aber die Dinge widersprachen meinen Erwartungen. Timerone schläft (4000), schläft 4S und der Timer befindet sich im Timer, wodurch die Zeit für TimeOne das Intervall überschreitet. Das Ergebnis:
Timerone aufgerufen, die Zeit: 1000
Timerone aufgerufen, die Zeit: 5000
2) Timer wirft Ausnahmemangel aus
Wenn TimerTask eine RunTimeException auswirkt, beendet der Timer alle Aufgaben. wie folgt:
public class timertest04 {privater Timer -Timer; public timertest04 () {this.Timer = new Timer (); } public void Timerone () {Timer.Schedule (neuer TimerTask () {public void run () {throw New RunTimeException ();}}, 1000); } public void timerTwo () {timer.Schedule (neuer Timertask () {public void run () {System.out.println ("werde ich es ausführen?");}}, 1000); } public static void main (String [] args) {timertest04 test = new timertest04 (); test.timerone (); test.timertwo (); }} Auslaufergebnis: Timerone löst eine Ausnahme aus und führt dazu, dass die TimerTwo -Aufgabe beendet wird.
Ausnahme in Thread "Timer-0" java.lang.runtimeexception bei com.chenssy.timer.timerTest04 $ 1.run (timerTest04.java:25) bei Java.util.TimerThread.Mainloop (Timer.java:555) in java.util.til.timerthead.run.run (timer.java:505).
Bei Timer -Mängel können wir geplante Threadpoolexecutor als Ersatz in Betracht ziehen. Timer basiert auf absoluter Zeit und reagiert empfindlicher für die Systemzeit, während geplant Threadpoolexecutor auf der relativen Zeit basiert. Timer ist intern ein einzelner Thread, während geplanter Threadpoolexecutor intern ein Thread -Pool ist, sodass er die gleichzeitige Ausführung mehrerer Aufgaben unterstützt.
3.2. Timer ersetzen
1) Lösen Sie das Problem eins:
öffentliche Klasse ScheduledexecUTORTEST {private enderEDexecutorService afuexec; öffentlicher langer Start; EnderEdexecUTORTEST () {this.Scheduexec = Executors.NewScheduledThreadpool (2); this.start = system.currentTimemillis (); } public void Timerone () {enderUexec.schedule (new Runnable () {public void run () {System.out.println ("Timeron, die Zeit:" + (System.CurrentTimemillis () - Start); Try {Thread.Sleep (4000); }, 1000, TimeUnit.Millisekunden); } public void timerTwo () {planeLexexec.Schedule (new Runnable () {public void run () {System.out.println ("timerTwo, the the the the time:" + (System.currentTimemillis () - Start);}}, 2000, Timeunit.Milliseconds); } public static void main (String [] args) {teplanexecutportest test = new afuleDexecUTORTEST (); test.timerone (); test.timertwo (); }} Auslaufergebnisse:
Timerone, die Zeit: 1003
TIMERTWO, THE TIME: 2005
2) Lösen Sie das Problem zwei
öffentliche Klasse ScheduledexecUTORTEST {private enderEDexecutorService afuexec; öffentlicher langer Start; EnderEdexecUTORTEST () {this.Scheduexec = Executors.NewScheduledThreadpool (2); this.start = system.currentTimemillis (); } public void Timerone () {enderUexec.schedule (new Runnable () {public void run () {neue runTimeException ();}}, 1000, TimeUnit.Milliseconds); } public void timerTwo () {planeLexexec.SchulenatFixedRate (new Runnable () {public void run () {System.out.println ("timerTwo aufgerufen .....");}}, 2000.500, timeunit.milliseconds); } public static void main (String [] args) {teplanexecutportest test = new afuleDexecUTORTEST (); test.timerone (); test.timertwo (); }} Auslaufergebnisse:
TIMERERTWO aufgerufen ... TIMERTWO aufgerufen ... TIMERTWO aufgerufen ... TIMERERTWO aufgerufen ... TIMERTWO aufgerufen ... TIMERTWO aufgerufen ... TIMERTWO Invooked ... TIMERERTWO Invooked ... TIMERERTWO aufgerufen ... TimerTwo aufgerufen ...
Das obige ist der gesamte Inhalt dieses Artikels. Hier geht es um Java -Timing -Aufgaben. Ich hoffe, es wird für Ihr Lernen hilfreich sein.