2008-08-28 69 views
36

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

Si, sin embargo, antes de que transcurran X segundos, decido que el evento debe ocurrir después de Y segundos, entonces quiero poder decirle al temporizador que restablezca su hora para que el evento ocurra en Y segundos. P. ej. el temporizador debe ser capaz de 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 utilizando el temporizador de utilidades, como si se llama a cancelar() no se puede programar de nuevo.

La única forma en que he estado cerca de replicar este comportamiento es mediante el uso de 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 alguna manera más fácil?

Respuesta

48

Según la documentación Timer, en Java 1.5 en adelante, debería preferir el ScheduledThreadPoolExecutor en su lugar. (Es posible que desee para crear esta ejecutor utilizando Executors.newSingleThreadScheduledExecutor() para facilitar su uso;. Crea algo muy parecido a un Timer)

Lo bueno es decir, cuando se programa una tarea (llamando schedule()), devuelve un objeto ScheduledFuture . Puede usar esto para cancelar la tarea programada. Entonces puede enviar una nueva tarea con un tiempo de disparo diferente.

ETA: La documentación Timer vinculado a no dice nada acerca de ScheduledThreadPoolExecutor, sin embargo la versión OpenJDK dijo lo siguiente:

Java 5.0 introduce el paquete java.util.concurrent y una de las utilidades de concurrencia en él la ScheduledThreadPoolExecutor que es un grupo de subprocesos repetidamente ejecutando tareas a una tasa o retraso dados. Es más efectiva una reemplazo versátil para la combinación Timer/TimerTask , ya que permite que múltiples hilos de servicio, acepta varias unidades de tiempo, y no requiere la subclasificación TimerTask (justo aplicar Runnable). Configurar ScheduledThreadPoolExecutor con un hilo lo hace equivalente a Timer.

+0

Se habla de ScheduledThreadPoolExecutor en este temporizador: http://developer.android.com/reference/java/util/Timer.html –

+0

El problema con este enfoque es que ya no tiene acceso a 'TimerTask .scheduledExecutionTime() 'dentro de su tarea. No podrá determinar si la tarea es "tardía" y no debería ejecutarse. –

+2

use 'myScheduledThreadPoolExecutor.getQueue(). Clear()' para eliminar todas las tareas programadas que aún no se han ejecutado, pero no puede usar esta técnica con 'Executors.newSingleThreadScheduledExecutor()' en su lugar, debe instanciar un 'nuevo ScheduledThreadPoolExecutor (1) 'porque solo los métodos de interfaz están expuestos en el objeto devuelto por el Ejecutor. – gMale

1

¿Necesita programar una tarea recurrente? En ese caso, le recomiendo que considere usar Quartz.

1

No creo que sea posible hacerlo con Timer/TimerTask, pero dependiendo de lo que exactamente quiera lograr, puede estar contento con el uso de java.util.concurrent.ScheduledThreadPoolExecutor.

17

Si su Timer única es cada vez va a tener una tarea a ejecutar entonces sugeriría la subclasificación que:

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

Usted tendrá que trabajar en el código para agregar los controles de mal uso, pero debería lograr lo que quieres. El ScheduledThreadPoolExecutor no parece haber incorporado el soporte para reprogramar las tareas existentes tampoco, pero un enfoque similar debería funcionar allí también.

1

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

en mi clase principal, guardo la instancia del temporizador y una instancia de mi subclase local de TimerTask. la clase principal tiene un método para establecer el intervalo de sondeo (por ejemplo, pasar de 60 a 30). en él, cancelo mi TimerTask (que es mi subclase, donde sobreescribí el método cancel() para hacer algo de limpieza, pero eso no debería importar) y luego lo hice nulo. recreo una nueva instancia de la misma, 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 lo mismo ocurriría con cualquier otro TimerTasks dentro de él), y el antiguo TimerTask se reemplaza por uno nuevo, que pasa a ser el mismo, pero VIRGIN (ya que el anterior se habría ejecutado o programado, ya no es VIRGIN, como se requiere para la programación).

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

3

todo el fragmento de código dice así .... espero que será 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);   
     } 
     } 


} 
0

Aquí está el ejemplo de Resetable temporizador. Tratar de cambiarlo para su 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)); 
    } 
} 

Este ejemplo imprime la fecha y hora actuales para cada 5 segundos ... Pero si se le da ninguna entrada en la consola el temporizador se retrasará para realizar la entrada dada tarea ...