tiempo - Temporizador Java reiniciable
timer java 8 (8)
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.
Sin embargo, si antes de X segundos ha transcurrido, 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. Por ejemplo, el temporizador debería 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 hacerlo con el temporizador de utils, como si llamaras a cancel () no puedes volver a programarlo.
La única forma en que he estado cerca de 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??
¿Necesitas programar una tarea recurrente? En ese caso, te recomiendo que consideres usar Quartz .
Aquí está el ejemplo para el Temporizador reajustable. Intenta cambiarlo por 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 la hora actuales cada 5 segundos ... Pero si da cualquier entrada en la consola, el temporizador se retrasará para realizar la tarea de entrada dada ...
De acuerdo con la documentación del Timer
, en Java 1.5 en adelante, debe preferir el ScheduledThreadPoolExecutor
lugar. (Es posible que .newSingleThreadScheduledExecutor()
crear este ejecutor utilizando los Executors
.newSingleThreadScheduledExecutor()
para facilitar su uso, ya que crea algo parecido a un Timer
).
Lo bueno es que cuando planifica una tarea (llamando a 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 del Timer
vinculada no dice nada acerca de ScheduledThreadPoolExecutor
, sin embargo, la versión de OpenJDK tenía esto que decir:
Java 5.0 introdujo el paquete
java.util.concurrent
y una de las utilidades de simultaneidad en el mismo esScheduledThreadPoolExecutor
que es un grupo de subprocesos para ejecutar tareas repetidamente a una tasa o retraso dados. Es efectivamente un reemplazo más versátil para la combinaciónTimer
/TimerTask
, ya que permite múltiples hilos de servicio, acepta varias unidades de tiempo y no requiere la subclasificación deTimerTask
(simplemente implementeRunnable
). ConfigurarScheduledThreadPoolExecutor
con un hilo lo hace equivalente aTimer
.
Hice una clase propia de temporizador 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);
}
}
No creo que sea posible hacerlo con Timer/TimerTask
, pero dependiendo de lo que quieras lograr, podrías estar contento con el uso de java.util.concurrent.ScheduledThreadPoolExecutor
.
Si su Timer
solo va a tener una tarea que ejecutar, le sugiero que la subclasifique:
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 cheques por mal uso, pero debería lograr lo que quiere. El ScheduledThreadPoolExecutor
tampoco parece tener soporte para la reprogramación de tareas existentes, pero un enfoque similar debería funcionar allí también.
Todo el fragmento de código es 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);
}
}
}
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í mismo no se cancela, el hilo que estaba usando permanece activo (y lo mismo ocurriría con cualquier otro TimerTasks dentro de él), y el viejo TimerTask se reemplaza con uno nuevo, que pasa a ser el mismo, pero VIRGIN (dado 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.