Pregunta

Me gustaría tener un java.utils.Timer con un tiempo reiniciable en java. Necesito configurar un evento único para que ocurra en X segundos.Si no sucede nada entre el momento en que se creó el temporizador y X segundos, entonces el evento ocurre normalmente.

Sin embargo, si antes de que hayan transcurrido X segundos, decido que el evento debería ocurrir después de Y segundos, entonces quiero poder decirle al temporizador que reinicie su tiempo para que el evento ocurra en Y segundos.P.ej.el temporizador debería poder hacer algo como:

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

No veo una manera de hacer esto usando el temporizador de utilidades, ya que si llamas a cancelar() no puedes programarlo nuevamente.

La única forma en que me he acercado a replicar este comportamiento es usando javax.swing.Timer e implica detener el temporizador original y crear uno nuevo.es decir.:

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

¿¿Hay una manera mas facil??

¿Fue útil?

Solución

De acuerdo con la Timer documentación, en Java 1.5 en adelante, debería preferir la ScheduledThreadPoolExecutor en cambio.(Es posible que desee crear este ejecutor usando Executors.newSingleThreadScheduledExecutor() para facilitar su uso;crea algo muy parecido a un Timer.)

Lo bueno es que, cuando programa una tarea (llamando schedule()), devuelve un ScheduledFuture objeto.Puede utilizar esto para cancelar la tarea programada.Luego podrá enviar una nueva tarea con un tiempo de activación diferente.

Hora estimada de llegada:El Timer La documentación vinculada a no dice nada sobre ScheduledThreadPoolExecutor, sin embargo, el AbiertoJDK La versión decía esto:

Java 5.0 introdujo el java.util.concurrent paquete y una de las utilidades de concurrencia en el mismo es el ScheduledThreadPoolExecutor que es un grupo de hilos para ejecutar repetidamente tareas a una tasa o retraso determinado.Es efectivamente un reemplazo más versátil para el Timer/TimerTaskLa combinación, ya que permite múltiples hilos de servicio, acepta varias unidades de tiempo y no requiere subclases TimerTask (solo implementa Runnable).Configurando ScheduledThreadPoolExecutor con un hilo lo hace equivalente a Timer.

Otros consejos

Si tu Timer solo tendrá una tarea para ejecutar, entonces sugeriría subclasificarla:

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

Tendrá que trabajar en el código para agregar comprobaciones por mal uso, pero debería lograr lo que desea.El ScheduledThreadPoolExecutor Tampoco parece haber incorporado soporte para reprogramar tareas existentes, pero un enfoque similar también debería funcionar allí.

Todo el fragmento de código dice así...Espero que sea de ayuda completa.

{

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


}

¿Necesitas programar una tarea recurrente?En ese caso te recomiendo que consideres usar Cuarzo.

No creo que sea posible hacerlo con Timer/TimerTask, pero dependiendo de lo que quieras lograr exactamente, es posible que estés satisfecho con el uso java.util.concurrent.ScheduledThreadPoolExecutor.

esto es lo que estoy probando.Tengo una clase que sondea una base de datos cada 60 segundos usando TimerTask.

en mi clase principal, mantengo la instancia de Timer y una instancia de mi subclase local de TimerTask.la clase principal tiene un método para establecer el intervalo de sondeo (por ejemplo, de 60 a 30).en él, cancelo mi TimerTask (que es mi subclase, donde sobrescribí el método cancel() para hacer una limpieza, pero eso no debería importar) y luego lo hago nulo.Vuelvo a crear una nueva instancia y programo la nueva instancia en el nuevo intervalo en el temporizador existente.

Dado que el temporizador en sí no se cancela, el hilo que estaba usando permanece activo (y también lo haría cualquier otro TimerTasks dentro de él), y el antiguo TimerTask se reemplaza por uno nuevo, que resulta ser el mismo, pero VIRGEN (desde el el anterior hubiera sido ejecutado o programado, ya no es VIRGEN, como se requiere para la programación).

cuando quiero apagar todo el temporizador, cancelo y anulo TimerTask (lo mismo que hice cuando cambié el tiempo, nuevamente, para limpiar recursos en mi subclase de TimerTask), y luego cancelo y anulo el propio temporizador.

Aquí está el ejemplo de Temporizador reiniciable.Intenta cambiarlo para tu conveniencia...

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

Este ejemplo imprime la fecha y hora actuales cada 5 segundos...Pero si proporciona alguna entrada en la consola, el temporizador se retrasará para realizar la tarea de entrada dada...

Hice una clase de temporizador propia para un propósito similar;Sientase libre de usarlo:

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);
  }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top