Close

Java - Scheduled Thread Pools

[Last Updated: Jun 10, 2022]

Scheduled executors are based on the interface ScheduledExecutorService which extends ExecutorService interface.

ScheduledExecutorService supports delayed and periodic execution of one or more submitted tasks, whereas ExecutorService supports just one time task execution of one or more submitted tasks.

ScheduledExecutorService is a convenient alternative to java.util.Timer for scheduling the tasks execution, just like ExecutorService is a convenient alternative to java.lang.Thread.


ScheduledExecutorService introduces new methods to create tasks with delays and periodicity properties.




Note that ScheduledExecutorService#scheduledWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) has different meanings than Timer#Schedule(TimerTask task, long delay, long period), even though both are termed as fixed-delayed tasks in the API docs. The former meanings of delay refers to a fixed delay which separates every two tasks, whereas the latter (please explore details here) refers to rather fixed-delay frequency where delay always starts at the begging of each task executions rather than at the end.



The ScheduledFuture interface

All methods in ScheduledExecutorService interface return ScheduledFuture. This interface extends Future, Delayed and Comparable interfaces.

Future interface is mainly used to get the results of a Callable results.

Delayed interface is used to indicate that this object supports some sort of delayed period.

ScheduledExecutorService doesn't define any new method of its own.


The ScheduledThreadPoolExecutor class

This class extends ThreadPoolExecutor and implements ScheduledFuture.

This implementation can run multiple submitted tasks in parallel (the pool concept). If we compare this to java.util.Timer, one Timer instance uses only one thread even if multiple tasks are submitted. So basically all multiple tasks, we submit to a Timer instance, run in sequence to each other but over all execution run in a new thread. ScheduledThreadPoolExecutor can run multiple tasks periodically in parallel depending on the pool size.

Let's explore ScheduledThreadPoolExecutor constructors quickly:

ScheduledThreadPoolExecutor(int corePoolSize)

ScheduledThreadPoolExecutor(int corePoolSize, RejectedExecutionHandler handler)

ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory)

ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory, RejectedExecutionHandler handler)

Comparing with the constructors of the super class ThreadPoolExecutor (which we explored here), there's no new properties provided at the construction time. Also it doesn't provide most of the super class construction time parameters. Most importantly it doesn't provide a way to specify construction time BlockingQueue<Runnable> workQueue option like its super class. The reason is: this pool implementation uses only unbounded queue. According to ScheduledThreadPoolExecutor docs:

While this class inherits from ThreadPoolExecutor, a few of the inherited tuning methods are not useful for it. In particular, because it acts as a fixed-sized pool using corePoolSize threads and an unbounded queue, adjustments to maximumPoolSize have no useful effect. Additionally, it is almost never a good idea to set corePoolSize to zero or use allowCoreThreadTimeOut because this may leave the pool without threads to handle tasks once they become eligible to run.

Example Project

This example project includes scenarios where a single task or multiple tasks are submitted to the ScheduledThreadPoolExecutor instance having pool size one or two.

Dependencies and Technologies Used:

  • JDK 1.8
  • Maven 3.0.4

Scheduled Executor Example Project Select All Download
  • thread-scheduled-pools-example
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • ScheduledSingleFixedDelayTask.java

    See Also