Question

J'aimerais avoir un java.utils.Minuterie avec un temps programmable en java.J'ai besoin de régler en une fois un événement de se produire dans les X secondes.Si rien ne se passe entre le moment de la minuterie a été créé et les X secondes, puis l'événement se produit comme d'habitude.

Si, toutefois, avant de les X secondes s'est écoulé, j'ai décider que l'événement devrait se produire après Y secondes au lieu de cela, je veux être en mesure de dire que la minuterie de réinitialisation de son temps, de sorte que l'événement se produit dans les Y secondes.E. g.le minuteur doit être en mesure de faire quelque chose comme:

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).

Je ne vois pas le moyen de le faire à l'aide de la utils à rebours, comme si vous appelez annuler() vous ne pouvez pas planifier à nouveau.

La seule façon que je suis venu près de reproduire ce comportement est par l'utilisation de javax.swing.Minuterie et implique l'arrêt de l'original de la minuterie, et en créer un nouveau.c'est à dire:

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

Est-il un moyen plus facile??

Était-ce utile?

La solution

Selon l' Timer la documentation, en Java 1.5-delà, vous devez préférer les ScheduledThreadPoolExecutor au lieu de cela.(Comme vous pouvez le créer cette exécuteur testamentaire à l'aide de Executors.newSingleThreadScheduledExecutor() pour la facilité d'utilisation;il crée quelque chose de beaucoup plus comme un Timer.)

Le truc cool, c'est, lorsque vous planifiez une tâche (en appelant schedule()), elle renvoie un ScheduledFuture objet.Vous pouvez l'utiliser pour annuler la tâche planifiée.Vous êtes ensuite libre de soumettre une nouvelle tâche avec un autre déclenchement temps.

ETA:L' Timer la documentation liée à ne rien dire à ce sujet ScheduledThreadPoolExecutor, cependant l' OpenJDK version avait ceci à dire:

Java 5.0 a introduit le java.util.concurrent paquet et celui de la simultanéité des utilitaires y est la ScheduledThreadPoolExecutor qui est un pool de threads pour à plusieurs reprises l'exécution de tâches à un taux ou d'un retard.C'est effectivement un plus polyvalent de remplacement pour les Timer/TimerTask combinaison, car il permet à plusieurs threads de service, accepte divers les unités de temps, et ne nécessite pas de sous-classement TimerTask (juste mettre en œuvre Runnable).La configuration ScheduledThreadPoolExecutor avec un fil le rend équivalent à Timer.

Autres conseils

Si votre Timer n'est-il jamais d'avoir une tâche à exécuter alors je suggère de sous-classement:

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);
    }
}

Vous aurez besoin de travailler sur le code pour ajouter des contrôles de la mauvaise utilisation, mais il devrait obtenir ce que vous voulez.L' ScheduledThreadPoolExecutor ne semble pas avoir de prise en charge intégrée pour le rééchelonnement des tâches existantes, soit, mais une approche similaire devrait y travaillent ainsi.

L'ensemble de l'extrait de Code qui va comme ceci ....J'espère que ce sera de l'aide totale

{

        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);        
        }
      }


}

Avez-vous besoin pour planifier une tâche récurrente?Dans ce cas, je vous recommande de considérer l'utilisation de Quartz.

Je ne pense pas que c'est possible de le faire avec Timer/TimerTask, mais selon ce exactement que vous voulez atteindre, vous pourriez être heureux avec l'aide de java.util.concurrent.ScheduledThreadPoolExecutor.

c'est ce que je suis en train de sortir.J'ai une classe qui interroge une base de données de toutes les 60 secondes à l'aide d'un TimerTask.

dans ma classe principale, je garde l'exemple de la Minuterie, et une instance de ma sous-classe de TimerTask.la classe principale dispose d'une méthode pour définir l'intervalle d'interrogation (dire d'aller de 60 à 30).pour cela, j'ai annuler mon TimerTask (ce qui est mon sous-classe, où je écrasait la méthode cancel() pour faire un peu de ménage, mais qui ne le sont pas) et puis de la rendre nulle.j'ai recréer une nouvelle instance de celle-ci, et le calendrier de la nouvelle instance à la nouvelle fréquence dans l'état actuel de la Minuterie.

depuis la Minuterie n'est pas annulé, le fil c'est à l'aide des séjours actifs (et donc le feriez pour tout autre TimerTasks à l'intérieur), et l'ancien TimerTask est remplacé par un nouveau, qui se trouve être le même, mais VIERGE (depuis l'ancien aurait été exécutées ou prévues, il n'est plus VIERGE, tel que requis pour la planification).

quand je veux l'arrêt de l'ensemble de la minuterie, j'annule et null la TimerTask (même que je l'ai fait lors de la modification du calendrier, encore une fois, de nettoyage des ressources dans mon sous-classe de TimerTask), puis-je annuler et null la Minuterie de lui-même.

Voici l'exemple pour Resetable de la Minuterie .Essayer de le modifier pour votre convinence...

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));
    }
}

Cet exemple imprime la date et l'heure actuelles pour toutes les 5 secondes...Mais si vous donnez de l'entrée dans la console de la minuterie sera retardé pour effectuer la tâche d'entrée...

J'ai fait une classe timer pour un objet analogue;n'hésitez pas à utiliser:

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);
  }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top