Skip to content

14 ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutor

Como hemos visto, el Executor framework proporciona la clase ThreadPoolExecutor para ejecutar tareas Callable y Runnable con un grupo de hilos, sin que tengamos que preocuparnos de las operaciones de creación de los hilos. Cuando se envía una tarea al ejecutor, ésta es ejecutada lo más pronto que sea posible, teniendo en cuenta la configuración del ejecutor.

Sin embargo, algunas veces este comportamiento no es precisamente el deseado, sino que queremos que la tarea sea ejecutada una vez haya transcurrido un cierto lapso de tiempo.

Para este cometido, el Executor framework pone a nuestra disposición la interfaz ScheduledExecutorService, que extiende de ExecutorService, para definir una serie de métodos que van a permitir planificar cuándo queremos que se ejecute una tarea aproximadamente, e incluso que ésta se ejecute de forma periódica.

Veamos la definición de la interfaz ScheduledExecutorService:

public interface ScheduledExecutorService extends ExecutorService {

    // Métodos para retrasar un determinado tiempo la ejecución
    // de una tarea en el ejecutor.
    public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit);
    public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, 
                                           TimeUnit unit);

    // Métodos para planificar la ejecución periódica de una tarea
    // en el ejecutor.
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay,
                                                  long period, TimeUnit unit);
    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay,
                                                     long delay, TimeUnit unit);

}

La clase ScheduledThreadPoolExecutor extiende de ThreadPoolExecutor, por lo que incorpora toda su funcionalidad, pero además implementa la interfaz ScheduledExecutorService.

Esta clase ofrece distintos constructores sobrecargados, que nos permiten configurar el corePoolSize, el threadFactory y el rejectedExecutionHandler. Por ejemplo:

public class ScheduledThreadPoolExecutor extends ThreadPoolExecutor 
    implements ScheduledExecutorService {

    public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE,
              DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
              new DelayedWorkQueue());
    }

    // ...

}

Como vemos, por defecto se crea un cached threadpool executor, que mantendrá como mínimo el número de hilos pasado como argumento al constructor. Por defecto, los hilos serán destruidos si están 10 milisegundos inactivos, siempre y cuando el número de hilos sea mayor que el valor mínimo pasado como argumento al constructor. Las tareas se mantendrán en un tipo especial de BlockingQueue<Runnable> llamada DelayedWorkQueue.

La clase Executors proporciona el método estático factoría Executors.newScheduledThreadPool(corePoolSize), que recibirá el número de hilos mínimos que queremos que tenga el threadpool del ejecutor. También proporciona el método Executors.newSingleThreadScheduledExecutor(), en el que el número mínimo de hilos a mantener en el threadpool será 1.