Frage

Ich hätte gerne einen java.utils.Timer mit einer zurücksetzbaren Zeit in Java. Ich muss ein einmaliges Ereignis festlegen, das in X Sekunden auftritt.Wenn zwischen der Erstellung des Timers und X Sekunden nichts passiert, tritt das Ereignis wie gewohnt ein.

Wenn ich jedoch vor Ablauf vonZ.B.Der Timer sollte in der Lage sein, Folgendes zu tun:

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 mithilfe des Utils-Timers zu tun, da Sie es nicht erneut planen können, wenn Sie cancel() aufrufen.

Die einzige Möglichkeit, dieses Verhalten auch nur annähernd zu reproduzieren, ist die Verwendung von javax.swing.Timer. Dazu gehört das Stoppen des ursprünglichen Timers und das Erstellen eines neuen.d.h.:

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

Gibt es einen einfacheren Weg??

War es hilfreich?

Lösung

Entsprechend der Timer Dokumentation, ab Java 1.5 sollten Sie die bevorzugen ScheduledThreadPoolExecutor stattdessen.(Vielleicht möchten Sie diesen Executor mit erstellen Executors.newSingleThreadScheduledExecutor() für eine einfache Handhabung;Es entsteht so etwas wie ein Timer.)

Das Coole ist, wenn Sie eine Aufgabe planen (per Anruf). schedule()), gibt es a zurück ScheduledFuture Objekt.Damit können Sie die geplante Aufgabe abbrechen.Sie können dann eine neue Aufgabe mit einem anderen Auslösezeitpunkt einreichen.

voraussichtliche Ankunftszeit:Der Timer Die verlinkte Dokumentation sagt nichts darüber aus ScheduledThreadPoolExecutor, jedoch die OpenJDK Version hatte folgendes zu sagen:

Java 5.0 führte das ein java.util.concurrent Paket und eines der darin enthaltenen Versorgungsunternehmen sind die ScheduledThreadPoolExecutor Dies ist ein Thread -Pool für die wiederholte Ausführung von Aufgaben zu einer bestimmten Rate oder Verzögerung.Es ist effektiv ein vielseitigerer Ersatz für die Timer/TimerTaskDie Kombination, wie sie mehrere Service -Threads ermöglicht, akzeptiert verschiedene Zeiteinheiten und erfordert keine Unterklasse TimerTask (Implementieren Sie einfach Runnable).Konfigurieren ScheduledThreadPoolExecutor mit einem Thread macht es gleichwertig Timer.

Andere Tipps

Wenn dein Timer wird es immer nur eine Aufgabe geben, die ausgeführt werden muss, dann würde ich vorschlagen, sie in eine Unterklasse zu unterteilen:

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 am Code arbeiten, um Prüfungen auf Missbrauch hinzuzufügen, aber er sollte das erreichen, was Sie wollen.Der ScheduledThreadPoolExecutor scheint auch keine Unterstützung für die Neuplanung bestehender Aufgaben eingebaut zu haben, aber ein ähnlicher Ansatz sollte auch dort funktionieren.

Der gesamte Codeausschnitt sieht so aus ....Ich hoffe, dass es hilfreich sein wird

{

        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, über die Verwendung nachzudenken Quarz.

Ich glaube nicht, dass das möglich ist Timer/TimerTask, aber je nachdem, was genau Sie erreichen möchten, könnten Sie mit der Verwendung zufrieden sein java.util.concurrent.ScheduledThreadPoolExecutor.

Das ist es, was ich gerade ausprobiere.Ich habe eine Klasse, die alle 60 Sekunden mithilfe einer TimerTask eine Datenbank 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 (z. B. von 60 auf 30).Darin breche ich meine TimerTask ab (das ist meine Unterklasse, in der ich die Methode cancel() überschrieben habe, um etwas aufzuräumen, aber das sollte keine Rolle spielen) und mache sie dann auf null.Ich erstelle eine neue Instanz davon neu und plane die neue Instanz im neuen Intervall im vorhandenen Timer.

Da der Timer selbst nicht abgebrochen wird, bleibt der Thread, den er verwendet hat, aktiv (und das gilt auch für alle anderen darin enthaltenen TimerTasks), und die alte TimerTask wird durch eine neue ersetzt, die zufällig dieselbe ist, aber VIRGIN (da die das alte wäre ausgeführt oder geplant worden, es ist nicht mehr VIRGIN, wie für die Planung erforderlich).

Wenn ich den gesamten Timer herunterfahren möchte, breche ich die TimerTask ab und setze sie auf Null (dasselbe, was ich getan habe, als ich das Timing erneut geändert habe, um Ressourcen in meiner Unterklasse von TimerTask zu bereinigen), und dann breche ich den Timer selbst ab und setze ihn auf Null.

Hier ist das Beispiel für einen rücksetzbaren Timer.Versuchen Sie es zu Ihrer Überzeugung 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 werden alle 5 Sekunden das aktuelle Datum und die aktuelle Uhrzeit gedruckt. Wenn Sie jedoch eine Eingabe in der Konsole vornehmen, wird der Timer verzögert, um die angegebene Eingabeaufgabe auszuführen.

Für einen ähnlichen Zweck habe ich eine eigene Timer-Klasse erstellt;Fühlen Sie sich frei, es zu verwenden:

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);
  }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top