Zurücksetzbarer Java-Timer

Ich hätte gerne einen java.utils.Timer mit einer rücksetzbaren Zeit in Java. Ich muss ein einmaliges Ereignis festlegen, das in X Sekunden auftritt. Wenn zwischen der Zeit, zu der der Timer erstellt wurde, und X Sekunden nichts passiert, tritt das Ereignis wie normal auf.

Wenn jedoch vor Ablauf von X Sekunden entschieden wird, dass das Ereignis nach Y Sekunden stattfinden soll, dann möchte ich dem Zeitgeber mitteilen können, dass er seine Zeit zurücksetzen soll, so dass das Ereignis in Y Sekunden auftritt. ZB sollte der Timer in der Lage sein, etwas zu tun wie:

Timer timer = new Timer(); timer.schedule(timerTask, 5000); //Timer starts in 5000 ms (X) //At some point between 0 and 5000 ms... setNewTime(timer, 8000); //timerTask will fire in 8000ms from NOW (Y). 

Ich sehe keine Möglichkeit, dies mit dem utils-Timer zu tun, als ob du cancel () aufrufen würdest.

Die einzige Möglichkeit, dieses Verhalten nachzuvollziehen, besteht in der Verwendung von javax.swing.Timer. Dazu muss der ursprüngliche Zeitgeber gestoppt und ein neuer erstellt werden. zB:

 timer.stop(); timer = new Timer(8000, ActionListener); timer.start(); 

Gibt es einen leichteren Weg ??

Gemäß der Timer Dokumentation sollten Sie in Java 1.5 stattdessen den ScheduledThreadPoolExecutor bevorzugen. (Sie können diesen Executor unter Verwendung von Executors .newSingleThreadScheduledExecutor() zur einfacheren Verwendung erstellen. Er erstellt etwas, das einem Timer .)

Die coole Sache ist, wenn Sie einen Task (durch Aufruf von schedule() ) schedule() , gibt es ein ScheduledFuture Objekt zurück. Sie können dies verwenden, um die geplante Aufgabe abzubrechen. Sie können dann eine neue Aufgabe mit einer anderen Auslösezeit einreichen.

ETA: Die mit verknüpfte Timer Dokumentation sagt nichts über ScheduledThreadPoolExecutor , aber die OpenJDK- Version hatte folgendes zu sagen:

Java 5.0 führte das Paket java.util.concurrent , und eines der darin enthaltenen Programme für den gemeinsamen Zugriff ist der ScheduledThreadPoolExecutor der ein Thread-Pool zum wiederholten Ausführen von Aufgaben mit einer bestimmten Rate oder Verzögerung ist. Es ist effektiv ein vielseitigerer Ersatz für die Timer / TimerTask Kombination, da es mehrere Dienst-Threads erlaubt, verschiedene Zeiteinheiten akzeptiert und keine Unterklasse von TimerTask erfordert (nur Runnable implementieren). Wenn Sie ScheduledThreadPoolExecutor mit einem Thread konfigurieren, entspricht dies Timer .

Wenn Ihr Timer immer nur eine Aufgabe ausführen soll, würde ich vorschlagen, diese zu untergliedern:

 import java.util.Timer; import java.util.TimerTask; public class ReschedulableTimer extends Timer { private Runnable task; private TimerTask timerTask; public void schedule(Runnable runnable, long delay) { task = runnable; timerTask = new TimerTask() { @Override public void run() { task.run(); } }; this.schedule(timerTask, delay); } public void reschedule(long delay) { timerTask.cancel(); timerTask = new TimerTask() { @Override public void run() { task.run(); } }; this.schedule(timerTask, delay); } } 

Sie müssen an dem Code arbeiten, um Überprüfungen für Missbrauch hinzuzufügen, aber es sollte erreichen, was Sie wollen. Der ScheduledThreadPoolExecutor scheint keine Unterstützung für die Umplanung vorhandener Tasks zu bieten, aber ein ähnlicher Ansatz sollte auch dort funktionieren.

Das ganze Code-Snippet geht so …. Ich hoffe es wird volle Hilfe sein

 { Runnable r = new ScheduleTask(); ReschedulableTimer rescheduleTimer = new ReschedulableTimer(); rescheduleTimer.schedule(r, 10*1000); public class ScheduleTask implements Runnable { public void run() { //Do schecule task } } class ReschedulableTimer extends Timer { private Runnable task; private TimerTask timerTask; public void schedule(Runnable runnable, long delay) { task = runnable; timerTask = new TimerTask() { public void run() { task.run(); } }; timer.schedule(timerTask, delay); } public void reschedule(long delay) { System.out.println("rescheduling after seconds "+delay); timerTask.cancel(); timerTask = new TimerTask() { public void run() { task.run(); } }; timer.schedule(timerTask, delay); } } } 

Müssen Sie eine wiederkehrende Aufgabe planen? In diesem Fall empfehle ich Ihnen, Quarz zu verwenden .

Ich denke nicht, dass es möglich ist, es mit Timer/TimerTask zu tun, aber abhängig davon, was genau Sie erreichen möchten, können Sie mit java.util.concurrent.ScheduledThreadPoolExecutor glücklich sein.

das ist es, was ich ausprobiere. Ich habe eine class, die alle 60 Sekunden eine database mit einer TimerTask abfragt.

In meiner Hauptklasse behalte ich die Instanz des Timers und eine Instanz meiner lokalen Unterklasse von TimerTask. Die Hauptklasse verfügt über eine Methode zum Festlegen des Abfrageintervalls (von 60 bis 30). Darin kündige ich meine TimerTask (was meine Unterklasse ist, wo ich die cancel () -Methode überschrieben habe, um etwas zu bereinigen, aber das sollte nicht wichtig sein) und mache dann null. Ich erstelle eine neue Instanz davon und plane die neue Instanz im neuen Intervall im vorhandenen Timer ein.

Da der Timer selbst nicht abgebrochen wird, bleibt der verwendete Thread aktiv (und auch andere TimerTasks in ihm), und die alte TimerTask wird durch eine neue ersetzt, die gleich ist, aber VIRGIN (seit der der alte wäre ausgeführt worden oder geplant worden, es ist nicht länger VIRGIN, wie für die Planung erforderlich).

Wenn ich den gesamten Timer herunterfahren möchte, annulliere und nulle ich die TimerTask (genau wie ich es getan habe, wenn ich das Timing wieder ändere, um Ressourcen in meiner Unterklasse von TimerTask zu bereinigen), und annulliere und nulle den Timer selbst.

Hier ist das Beispiel für einen rücksetzbaren Timer. Versuche es für deine Konvidenz zu ändern …

 package com.tps.ProjectTasks.TimeThread; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Timer; import java.util.TimerTask; /** * Simple demo that uses java.util.Timer to schedule a task to execute * every 5 seconds and have a delay if you give any input in console. */ public class DateThreadSheduler extends Thread { Timer timer; BufferedReader br ; String data = null; Date dNow ; SimpleDateFormat ft; public DateThreadSheduler() { timer = new Timer(); timer.schedule(new RemindTask(), 0, 5*1000); br = new BufferedReader(new InputStreamReader(System.in)); start(); } public void run(){ while(true){ try { data =br.readLine(); if(data != null && !data.trim().equals("") ){ timer.cancel(); timer = new Timer(); dNow = new Date( ); ft = new SimpleDateFormat ("E yyyy.MM.dd 'at' hh:mm:ss a zzz"); System.out.println("Modified Current Date ------> " + ft.format(dNow)); timer.schedule(new RemindTask(), 5*1000 , 5*1000); } }catch (IOException e) { e.printStackTrace(); } } } public static void main(String args[]) { System.out.format("Printint the time and date was started...\n"); new DateThreadSheduler(); } } class RemindTask extends TimerTask { Date dNow ; SimpleDateFormat ft; public void run() { dNow = new Date(); ft = new SimpleDateFormat ("E yyyy.MM.dd 'at' hh:mm:ss a zzz"); System.out.println("Current Date: " + ft.format(dNow)); } } 

In diesem Beispiel wird das aktuelle Datum und die aktuelle Uhrzeit alle 5 Sekunden ausgegeben … Wenn Sie jedoch eine Eingabe in der Konsole eingeben, wird der Timer verzögert, um die angegebene Eingabe auszuführen …

Ich habe eine eigene Timer-class für einen ähnlichen Zweck gemacht; Fühlen Sie sich frei, es zu benutzen:

 public class ReschedulableTimer extends Timer { private Runnable mTask; private TimerTask mTimerTask; public ReschedulableTimer(Runnable runnable) { this.mTask = runnable; } public void schedule(long delay) { if (mTimerTask != null) mTimerTask.cancel(); mTimerTask = new TimerTask() { @Override public void run() { mTask.run(); } }; this.schedule(mTimerTask, delay); } }