Ich habe ähnliche Fragen hier gestellt, aber zu meiner Zufriedenheit gab es keine Antworten. Also formuliere die Frage noch einmal
Ich habe eine Aufgabe, die regelmäßig erledigt werden muss (sagen wir alle 1 Minute). Welchen Vorteil bietet Timertask & Timer dazu, anstatt einen neuen Thread zu erstellen, der eine Endlosschleife mit Sleep hat.
Code-Snippet mit Zeittask
TimerTask uploadCheckerTimerTask = new TimerTask(){
public void run() {
NewUploadServer.getInstance().checkAndUploadFiles();
}
};
Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(uploadCheckerTimerTask, 0, 60 * 1000);
Code-Snippet mit Thread und Sleep-
Thread t = new Thread(){
public void run() {
while(true) {
NewUploadServer.getInstance().checkAndUploadFiles();
Thread.sleep(60 * 1000);
}
}
};
t.start();
Ich muss mir wirklich keine Sorgen machen, wenn ich bestimmte Zyklen vermisse, wenn die Ausführung der Logik mehr als die Intervallzeit benötigt.
Bitte kommentieren Sie dies ..
Aktualisieren:
Kürzlich fand ich einen anderen Unterschied zwischen der Verwendung von Timer und Thread.sleep (). Angenommen, die aktuelle Systemzeit ist 11:00 Uhr. Wenn wir die Systemzeit aus irgendeinem Grund auf 10:00 Uhr zurücksetzen, stoppt The Timer die Ausführung der Aufgabe bis zum Erreichen von 11:00 Uhr, während die Methode Thread.sleep () die Aufgabe ohne Behinderung fortsetzt. Dies kann ein wichtiger Entscheider bei der Entscheidung sein, was zwischen diesen beiden verwendet werden soll.
Der Vorteil von TimerTask ist, dass es Ihre Absicht viel besser zum Ausdruck bringt (d. H. Die Lesbarkeit von Code) und bereits die Funktion cancel () implementiert ist.
Beachten Sie, dass es sowohl in kürzerer Form als auch in Ihrem eigenen Beispiel geschrieben werden kann:
Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(
new TimerTask() {
public void run() { NewUploadServer.getInstance().checkAndUploadFiles(); }
}, 0, 60 * 1000);
Timer/TimerTask berücksichtigt auch die Ausführungszeit Ihrer Aufgabe, sodass sie etwas genauer ist. Außerdem werden Multithreading-Probleme (z. B. Vermeidung von Deadlocks usw.) besser behandelt. Und natürlich ist es in der Regel besser, statt einer hausgemachten Lösung einen gut getesteten Standardcode zu verwenden.
Ich weiß nicht warum, aber ein Programm, das ich schrieb, verwendete Timers und seine Heap-Größe nahm ständig zu, sobald ich es in ein Thread-/Schlaf-Problem geändert hatte.
Wenn der Thread eine Ausnahme erhält und beendet wird, stellt dies ein Problem dar. TimerTask kümmert sich darum. Es wird unabhängig vom Fehler des vorherigen Laufs ausgeführt.
Es gibt ein entscheidendes Argument gegen die Verwaltung dieser Aufgabe mit Java-Threads und der sleep
-Methode. Sie verwenden while(true)
, um unbegrenzt in der Schleife zu bleiben und den Thread in den Ruhezustand zu versetzen, indem Sie den Ruhezustand aktivieren. Was ist, wenn NewUploadServer.getInstance().checkAndUploadFiles();
einige synchronisierte Ressourcen in Anspruch nimmt. Andere Threads können nicht auf diese Ressourcen zugreifen. Es kann zu Verhungern kommen, was die gesamte Anwendung verlangsamen kann. Diese Art von Fehlern ist schwer zu diagnostizieren und es ist eine gute Idee, ihre Existenz zu verhindern.
Der andere Ansatz löst die Ausführung des Codes aus, der für Sie von Bedeutung ist, d. H. NewUploadServer.getInstance().checkAndUploadFiles();
, indem Sie die run()
-Methode Ihrer TimerTask
aufrufen, während andere Threads in der Zwischenzeit die Ressourcen verwenden.
Aus der Timer
Dokumentation :
Java 5.0 führte das Java.util.concurrent-Paket und eines der .__ ein. Nebenläuferdienstprogramme sind darin der ScheduledThreadPoolExecutor, der ist ein Thread-Pool für die wiederholte Ausführung von Aufgaben mit einer bestimmten Rate oder verzögern. Es ist effektiv ein vielseitiger Ersatz für die Timer/TimerTask-Kombination, da sie mehrere Service-Threads zulässt, akzeptiert verschiedene Zeiteinheiten und erfordert keine Unterklasse von TimerTask (Einfach Runnable implementieren). ScheduledThreadPoolExecutor .__ konfigurieren. mit einem Thread entspricht es dem Timer.
Also lieber ScheduledThreadExecutor
statt Timer
:
Timer
verwendet einen einzelnen Hintergrundthread, der zum sequenziellen Ausführen aller Tasks des Timers verwendet wird. Aufgaben sollten daher schnell abgeschlossen sein, andernfalls werden nachfolgende Aufgaben verzögert. Im Fall von ScheduledThreadPoolExecutor
können wir jedoch eine beliebige Anzahl von Threads konfigurieren und haben auch die vollständige Kontrolle, indem wir ThreadFactory
bereitstellen.Timer
kann empfindlich auf die Systemuhr reagieren, da sie die Object.wait(long)
-Methode verwendet. ScheduledThreadPoolExecutor
ist es nicht.ScheduledThreadPoolExecutor
behandeln können, so dass die anderen Aufgaben nicht betroffen sind.Timer
bietet die Methode cancel
, um den Timer zu beenden und geplante Tasks zu verwerfen. Dies wirkt sich jedoch nicht auf die aktuell ausgeführte Task aus. Wenn der Timer jedoch als Daemon-Thread ausgeführt wird, wird er abgebrochen, sobald alle Benutzer-Threads ausgeführt wurden.Der Timer verwendet Object.wait
und unterscheidet sich von Thread.sleep
wait
) kann (mit notify
) von einem anderen Thread benachrichtigt werden, ein ruhender Thread kann jedoch nicht unterbrochen werden. Er kann nur unterbrochen werden.Ich glaube, ich verstehe dein Problem, ich sehe etwas sehr ähnliches. Ich habe wiederkehrende Timer, alle 30 Minuten und alle paar Tage. Nach dem, was ich gelesen habe, und den Kommentaren, die ich sehe, sieht es so aus, als würde die Garbage Collection niemals ausgeführt, da alle Aufgaben nie abgeschlossen sind. Ich würde denken, dass die Speicherbereinigung laufen würde, wenn sich ein Timer im Schlaf befindet, aber ich sehe es nicht und der Dokumentation zufolge nicht.
Ich denke, dass das Auftauchen neuer Threads abgeschlossen ist und die Müllsammlung erlaubt.
Bitte beweisen Sie mir, dass jemand falsch ist. Was ich geerbt habe, wird ein Schmerz sein.