Hoy voy a hablar de los programadores de tareas de Java. En concreto las clases Timer y TimerTask.
Hay algo que tengo muy claro: No me gustan los hilos ni la concurrencia, así que todo API / utilidad que me abstraiga de utilizar y tener en cuenta toda esa parafernalia es bien recibida, máxime para cuando es algo que no te tiene que requerir mucho tiempo y (nunca mejor dicho) quedarte bloqueado hasta terminarla.
Así que más adelante, se muestra un ejemplo de cómo manejar Timer y TimerTask para ejecutar una tarea: cada día a la misma hora, para ejecutar cada 'n' horas, o 'n' minutos, para ejecutarla una vez a una hora concreta o ejecutarla una vez pasado un tiempo. Y todo esto Thread-Worry-Free. Maravilloso.
package es.snippetea;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Timer;
import java.util.TimerTask;
/**
*
* Programador de tareas que muestra el uso de la clase Timer
* junto con objetos de tipo TimerTask. Útiles cuando no puedes lanzar
* ejecuciones bloqueantes y no te quieres liar con concurrencia.
*
* @author icendrero
*/
public class ProgramadorDeTareas {
//Variables para decision de medida
public static final int HORAS = 0;
public static final int MINUTOS = 1;
public static final int SEGUNDOS = 2;
//Variables para tiempo en milisegundos
private static long unaHora = 3600000;
private static long unMinuto = 60000;
private static long unSegundo = 1000;
/**
*
* Esto ejecutará una tarea cada X tiempo hasta que se caiga la JVM
*
* @param cantidad
* @param medida
*/
public static void ejecutaTareaCadaXTiempo(int cantidad, int medida){
//Primero calculo cada cuanto ha de lanzarse(una hora, dos minutos...)
long periodo = 0;
switch (medida) {
case HORAS:
periodo = cantidad*unaHora;
break;
case MINUTOS:
periodo = cantidad*unMinuto;
break;
case SEGUNDOS:
periodo = cantidad*unSegundo;
break;
default:
periodo = -1;
}
//Si ya tenemos un intervalo, lo lanzamos
if(periodo!=-1){
Timer tareaEnIntervalo = new Timer();
//Creamos la tarea
AccionProgramada accionProgramada = new
AccionProgramada("lanzaTareaCadaXTiempo - ");
//La programamos
tareaEnIntervalo.scheduleAtFixedRate(
accionProgramada,
Calendar.getInstance().getTime(),
periodo);
}else{
System.out.println("No se lanzará ninguna tarea.");
}
}
/**
* Metodo que ejecuta una tarea diariamente. La ejecuta inmediatamente
* (aunque podría añadirse un retardo) y después la ejecutará a la misma
* hora todos los días.
*
* @param hora
* @param minutos
*/
public static void ejecutaTareaDiariamente(int hora, int minutos){
//Crea un nuevo calendario acutal
Calendar ahoraMismo = new GregorianCalendar();
int horaAhora = ahoraMismo.get(Calendar.HOUR_OF_DAY);
int minutosAhora = ahoraMismo.get(Calendar.MINUTE);
//Tiempo cuando se va a ejecutar por primera vez (y así repetidamente)
Calendar horaDeEjecucionDiaria = getHoraEjecucion(hora,minutos);
/*
* Si la hora que me especifican, es una hora pasada (a lo largo del día,
* p.ej me pasan como parámetro las 14:50 y son las 17:20)
*/
if (hora
//No ejecutar hoy, la primera ejecución será mañana
horaDeEjecucionDiaria.add(Calendar.DAY_OF_MONTH, 1);
}
//Cálculo para un día.
long unDiaEntero = 1000L * 60L * 60L * 24L;
//Creo un nuevo timer y obtengo el directorio de trabajo
Timer lanzaTareaDiariamente = new Timer();
AccionProgramada accionProgramada = new AccionProgramada("lanzaTareaDiariamente - ");
//Linea que es la que lanza el proceso que se ejecutará cada día
lanzaTareaDiariamente.scheduleAtFixedRate(
accionProgramada,
horaDeEjecucionDiaria.getTime(),
unDiaEntero);
}
/**
*
* Ejecuta una tarea a la hora que le digamos
*
* @param hora
* @param minutos
*/
public static void ejecutaTareaUnaVezAUnaHora(int hora, int minutos){
Timer lanzaUnaTarea = new Timer();
AccionProgramada accionProgramada = new
AccionProgramada("lanzaTareaUnaVezAUnaHora - ");
//Esto lo ejecutará una vez a esa hora.
lanzaUnaTarea.schedule(
accionProgramada,
getHoraEjecucion(hora,minutos).getTime());
}
/**
*
* Metodo que ejecuta una tarea pasado un tiempo
*
* @param cantidad
* @param medida
*/
public static void ejecutaTareaPasadoUnTiempo(int cantidad, int medida){
Timer lanzaUnaTareaRetardo = new Timer();
AccionProgramada accionProgramada = new AccionProgramada("lanzaTareaPasadoUnTiempo - ");
//Calculamos el retraso
long retraso = 0;
switch (medida) {
case HORAS:
retraso = cantidad*unaHora;
break;
case MINUTOS:
retraso = cantidad*unMinuto;
break;
case SEGUNDOS:
retraso = cantidad*unSegundo;
break;
default:
retraso = -1;
}
//Si ya tenemos un intervalo, lo lanzamos
if(retraso!=-1){
//Esto lo ejecutará una vez pasado ese tiempo.
lanzaUnaTareaRetardo.schedule(accionProgramada,retraso);
}else{
System.out.println("No se lanzará ninguna tarea.");
}
}
/**
*
* Método para obtener el Calendar de una hora en concreto.
*
* @param hora
* @param minutos
* @return El objeto Calendar.
*/
private static Calendar getHoraEjecucion(int hora, int minutos){
Calendar horaDeEjecucionDiaria = new GregorianCalendar();
horaDeEjecucionDiaria.set(Calendar.HOUR_OF_DAY, hora);
horaDeEjecucionDiaria.set(Calendar.MINUTE, minutos);
horaDeEjecucionDiaria.set(Calendar.SECOND, 0);
horaDeEjecucionDiaria.set(Calendar.MILLISECOND, 0);
return horaDeEjecucionDiaria;
}
//Main para probar
public static void main(String[] args) {
//Main para probar
public static void main(String[] args) {
System.out.println("-------------------------------------");
System.out.println("Lanzamiento de ejecutaTareaUnaVezAUnaHora"
+Calendar.getInstance().getTime());
ProgramadorDeTareas.ejecutaTareaUnaVezAUnaHora(16, 50);
System.out.println("-------------------------------------");
System.out.println("Lanzamiento de ejecutaTareaDiariamente"
+Calendar.getInstance().getTime());
ProgramadorDeTareas.ejecutaTareaDiariamente(16, 50);
System.out.println("-------------------------------------");
System.out.println("Lanzamiento de ejecutaTareaPasadoUnTiempo"
+Calendar.getInstance().getTime());
ProgramadorDeTareas.ejecutaTareaPasadoUnTiempo(20, ProgramadorDeTareas.SEGUNDOS);
System.out.println("-------------------------------------");
System.out.println("Lanzamiento de ejecutaTareaCadaXTiempo"
+Calendar.getInstance().getTime());
ProgramadorDeTareas.ejecutaTareaCadaXTiempo(1, ProgramadorDeTareas.MINUTOS);
System.out.println("-------------------------------------");
}
}
/**
* TimerTask de ejemplo.
* @author icendrero
*/
class AccionProgramada extends TimerTask{
/*
* Pequeño bean
*/
private String nombre;
public AccionProgramada(String nombre){
this.nombre = nombre;
}
/*
* Esto es lo que se ejecutará cuando le toque.
*/
@Override
public void run() {
System.out.println(nombre + " se ha ejecutado a las "+Calendar.getInstance().getTime());
}
}
Resultado:
-------------------------------------Lanzamiento de ejecutaTareaUnaVezAUnaHoraThu Oct 11 16:49:38 CEST 2012
------------------------------------
Lanzamiento de ejecutaTareaDiariamenteThu Oct 11 16:49:38 CEST 2012
-------------------------------------
Lanzamiento de ejecutaTareaPasadoUnTiempoThu Oct 11 16:49:38 CEST 2012
-------------------------------------
Lanzamiento de ejecutaTareaCadaXTiempoThu Oct 11 16:49:38 CEST 2012
-------------------------------------
lanzaTareaCadaXTiempo - se ha ejecutado a las Thu Oct 11 16:49:38 CEST 2012
lanzaTareaPasadoUnTiempo - se ha ejecutado a las Thu Oct 11 16:49:58 CEST 2012
lanzaTareaUnaVezAUnaHora - se ha ejecutado a las Thu Oct 11 16:50:00 CEST 2012
lanzaTareaDiariamente - se ha ejecutado a las Thu Oct 11 16:50:00 CEST 2012
lanzaTareaCadaXTiempo - se ha ejecutado a las Thu Oct 11 16:50:38 CEST 2012
lanzaTareaCadaXTiempo - se ha ejecutado a las Thu Oct 11 16:51:38 CEST 2012
lanzaTareaCadaXTiempo - se ha ejecutado a las Thu Oct 11 16:52:38 CEST 2012
Eh muchas gracias idolo...me sacaste de 3 dias sin hacer nada porque no podia encontrar como programar tareas...muy completo
ResponderEliminar