¿Cómo programar tareas recurrentes con java.util.concurrent.ScheduledExecutorService?

| Última modificación: 15 de enero de 2025 | Tiempo de Lectura: 3 minutos

Algunos de nuestros reconocimientos:

Premios KeepCoding

Puedes tener la súper memoria y ser de esas personas a las que nada se les escapa, pero en Java sí o sí hay que usar otras herramientas adicionales para no cansarse. Lo digo refiriéndome a que es tedioso tener que recordar cada cinco minutos enviar un mensaje, limpiar datos o actualizar una base de datos. Antes de java.util.concurrent.ScheduledExecutorService yo sentía que me iba a quedar sin cerebro. Pero ahora, gracias a esta herramienta puedo manejar este tipo de tareas periódicas o retrasadas, porque me ayuda a optimizar su ejecución en segundo plano. Si te estoy enredando mucho, mejor te lo explico por partes en este post.

java.util.concurrent.ScheduledExecutorService qué es

¿Qué es java.util.concurrent.ScheduledExecutorService?

Java.util.concurrent.ScheduledExecutorService es como tener un asistente personal que se encarga de programar y ejecutar tareas repetitivas o que tienen un retraso específico, como enviar un correo electrónico cada hora o hacer una copia de seguridad cada noche. Haz de cuenta que es un temporizador personalizable para tus aplicaciones.

Funcionamiento

  • Programa tus tareas: Es como poner una alarma en tu reloj. Le dices al asistente (ScheduledExecutorService) a qué hora quieres que se ejecute una tarea y él se encarga de recordártelo y ejecutarlo en el momento indicado.
  • Ejecución repetitiva: También puedes pedirle al asistente que repita una tarea cada cierto tiempo, como cada día, cada hora o cada minuto.
  • Flexibilidad: Puedes programar tareas para que se ejecuten una sola vez, de forma periódica o con un retraso inicial.

Entonces, con ScheduledExecutor podrás automatizar, programar y ejecutar tareas en segundo plano sin que se bloquee la ejecución de tu programa principal.

Métodos útiles de java.util.concurrent.ScheduledExecutorService

Al trabajar con esta interfaz, encontrarás estos cuatro métodos:

  1. schedule: Ejecuta una tarea después de un retraso especificado.
  2. scheduleAtFixedRate: Programa tareas para ejecutarse periódicamente con un intervalo fijo.
  3. scheduleWithFixedDelay: Programa tareas para ejecutarse con un retraso fijo entre ejecuciones.
  4. shutdown: Detiene el servicio una vez que todas las tareas se completan.

¿Cómo usar java.util.concurrent.ScheduledExecutorService?

Crea un ScheduledExecutorService

Como es una interfaz, no puedes instanciarla directamente. En su lugar, puedes usar la clase Executors para crear una instancia. Por ejemplo:

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(3);

Aquí creé un ScheduledExecutorService con un pool de tres hilos para manejar tareas concurrentes.

Programa una tarea única

Supongamos que quieres enviar un mensaje después de un retraso de 5 segundos:

import java.util.concurrent.*;

public class SingleTaskScheduler {
public static void main(String[] args) {
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

Runnable task = () -> System.out.println("¡Tarea ejecutada!");

scheduler.schedule(task, 5, TimeUnit.SECONDS);

scheduler.shutdown();
}
}

En este ejemplo, el mensaje se imprimirá en la consola 5 segundos después de ejecutar el programa.

Programa una tarea recurrente con intervalo fijo

Si necesitas realizar una tarea repetitiva, como limpiar archivos temporales cada 10 segundos, puedes usar scheduleAtFixedRate:

import java.util.concurrent.*;

public class FixedRateScheduler {
public static void main(String[] args) {
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);

Runnable task = () -> System.out.println("Limpieza ejecutada a las " + System.currentTimeMillis());

scheduler.scheduleAtFixedRate(task, 0, 10, TimeUnit.SECONDS);
}
}

¿Lo notaste? Aquí, la limpieza comienza inmediatamente y se repite cada 10 segundos.

Programa tareas con retraso fijo entre ejecuciones

Si necesitas esperar a que una tarea termine antes de comenzar otra, utiliza scheduleWithFixedDelay:

import java.util.concurrent.*;

public class FixedDelayScheduler {
public static void main(String[] args) {
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);

Runnable task = () -> {
System.out.println("Tarea iniciada a las " + System.currentTimeMillis());
try {
Thread.sleep(5000); // Simula un trabajo de 5 segundos
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
};

scheduler.scheduleWithFixedDelay(task, 0, 3, TimeUnit.SECONDS);
}
}

En este caso, cada tarea comienza 3 segundos después de que termina la anterior.

Ventajas de usar java.util.concurrent.ScheduledExecutorService

  1. Optimización de recursos: Reutiliza hilos para manejar múltiples tareas.
  2. Simplicidad: Facilita la programación de tareas repetitivas o retrasadas.
  3. Flexibilidad: Permite personalizar intervalos y retrasos según las necesidades de la aplicación.
  4. Manejo robusto de hilos: Reduce el riesgo de errores relacionados con la gestión manual de hilos.

Consejos al usar java.util.concurrent.ScheduledExecutorService

  • Siempre llama a shutdown para liberar recursos una vez que termines de usar el servicio.
  • Asegúrate de manejar excepciones dentro de las tareas, ya que un error no capturado puede interrumpir el servicio.

Ya lo sabes. Usa java.util.concurrent.ScheduledExecutorService para programar y ejecutar tareas recurrentes o retrasadas en Java. Con ejemplos como los que vimos, puedes implementar esta interfaz para optimizar la funcionalidad de tus aplicaciones de manera eficiente y profesional.

Convierte tu pasión en profesión dedicando horas inteligentes a tu crecimiento con KeepCoding. Apúntate al Bootcamp de Java Full Stack de KeepCoding. Dominarás desde conceptos básicos hasta técnicas avanzadas para crear aplicaciones robustas y escalables. ¡Es tu momento de entrar al mundo IT con el pie derecho!

Posts más leídos