Minuterie Java Réinitialisable

J'aimerais avoir un java.utils.Minuterie avec un temps réinitialisable en java.J'ai besoin de définir un événement once off pour se produire en X secondes. Si rien ne se passe entre le moment où la minuterie a été créée et X secondes, l'événement se produit normalement.

Si, cependant, avant X secondes s'est écoulé, je décide que l'événement devrait se produire après y secondes à la place, alors je veux être en mesure de dire à la minuterie de réinitialiser son heure afin que L'événement se produise en Y secondes. Par exemple, la minuterie devrait être capable 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 un moyen de le faire en utilisant la minuterie utils, comme si vous appelez cancel() vous ne pouvez pas le planifier à nouveau.

La seule façon de reproduire ce comportement est d'utiliser javax.swing.Minuterie et implique l'arrêt de la minuterie d'origine, et la création d'un nouveau. c'est à dire:

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

Y a-t-il un moyen plus facile??

36
demandé sur Lehane 2008-08-28 14:38:03

8 réponses

Selon le Timer documentation, dans Java 1.5 partir, vous devriez préférer le ScheduledThreadPoolExecutor au lieu de cela. (Vous pouvez créer cet exécuteur en utilisant Executors.newSingleThreadScheduledExecutor() pour la facilité d'utilisation; il crée quelque chose comme un Timer.)

Ce qui est cool, c'est que 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 alors libre de soumettre une nouvelle tâche avec un déclenchement différent temps.

ETA: la documentation Timer liée à ne dit rien sur ScheduledThreadPoolExecutor, cependant la version OpenJDK avait ceci à dire:

Java 5.0 a introduit le paquet java.util.concurrent et l'un des utilitaires de concurrence qui s'y trouve est le ScheduledThreadPoolExecutor qui est un pool de threads pour plusieurs fois exécuter des tâches à un rythme ou un délai donné. C'est effectivement un plus remplacement polyvalent pour le Timer / TimerTask la combinaison, car elle permet plusieurs threads de service, accepte divers unités de temps, et ne nécessite pas de sous-classement TimerTask (juste mettre en œuvre Runnable). Configuration ScheduledThreadPoolExecutor avec un thread le rend équivalent à Timer.

48
répondu Chris Jester-Young 2008-08-29 22:24:14

Si votre Timer n'aura qu'une seule tâche à exécuter, je suggérerais de la sous-classer:

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 devrez travailler sur le code pour ajouter des contrôles pour une mauvaise utilisation, mais cela devrait atteindre ce que vous voulez. Le ScheduledThreadPoolExecutor ne semble pas non plus avoir pris en charge le rééchelonnement des tâches existantes, mais une approche similaire devrait également fonctionner.

17
répondu David Sykes 2016-01-20 18:47:36

L'extrait de Code entier va comme ceci .... J'espère que ce sera une aide complète

{

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


}
3
répondu Shaik Khader 2014-05-24 00:17:23

Avez-vous besoin de planifier une tâche récurrente? Dans ce cas, je vous recommande d'utiliser Quartz .

1
répondu Brian Matthews 2008-08-28 10:54:30

Je ne pense pas qu'il soit possible de le faire avec Timer/TimerTask, mais en fonction de ce que vous voulez réaliser, vous pourriez être heureux d'utiliser java.util.concurrent.ScheduledThreadPoolExecutor.

1
répondu WMR 2008-08-28 11:47:18

C'est Ce que je suis en train de sortir. J'ai une classe qui interroge une base de données toutes les 60 secondes en utilisant 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 a une méthode pour définir l'intervalle d'interrogation (disons allant de 60 à 30). dans celui-ci, j'annule mon TimerTask (qui est ma sous-classe, où j'ai écrasé la méthode cancel() pour faire un peu de nettoyage, mais cela ne devrait pas avoir d'importance), puis le rendre null. je recrée une nouvelle instance de il, et planifier la nouvelle instance au nouvel intervalle dans la minuterie existante.

Puisque la minuterie elle-même n'est pas annulée, le thread qu'elle utilisait reste actif (et tout autre TimerTasks à l'intérieur), et L'ancien TimerTask est remplacé par un nouveau, qui se trouve être le même, mais vierge (puisque l'ancien aurait été exécuté ou planifié, il n'est plus vierge, comme requis pour la planification).

Quand je veux arrêter la minuterie entière, j'annule et annule la TimerTask (comme je l'ai fait en changeant le timing, encore une fois, pour nettoyer les ressources dans ma sous-classe de TimerTask), puis j'annule et annule la minuterie elle-même.

1
répondu 2009-04-16 14:09:11

Voici L'exemple de minuterie Réinitialisable . Essayez de le changer 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 affiche la date et l'heure actuelles toutes les 5 secondes...Mais si vous donnez une entrée dans la console, la minuterie sera retardée pour effectuer la tâche d'entrée donnée...

0
répondu Human Being 2012-12-05 09:53:52

J'ai fait une propre classe de minuterie dans un but similaire; n'hésitez pas à l'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);
  }
}
0
répondu luke8800gts 2018-07-20 16:33:21