ScheduledExecutorService – Running task in executor after delay

Learn to execute a task after a period of time or execute it periodically using ScheduledExecutorService class in Java using ScheduledThreadPoolExecutor.

1. ScheduledExecutorService interface

By default, Executor framework provides the ThreadPoolExecutor class to execute Callable and Runnable tasks with a pool of threads, which helps us avoid all thread creation boiler-plate code. When we send a task to the executor, it’s executed as soon as possible, according to the configuration of the executor.

But when we are not interested in executing a task as soon as possible and want to execute a task after a period of time or do it periodically, we can use ScheduledExecutorService interface along with its implementation, namely the ScheduledThreadPoolExecutor class.

public interface ScheduledExecutorService extends ExecutorService 
{
	public ScheduledFuture<?> schedule(Runnable command,
        	long delay, TimeUnit unit);

    public <V> ScheduledFuture<V> schedule(Callable<V> callable,
        	long delay, TimeUnit unit);

    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
		  	long initialDelay,
		  	long period,
		  	TimeUnit unit);

    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
          	long initialDelay,
         	long delay,
         	TimeUnit unit);
}
  • The schedule() methods create tasks with various delays and return a task object that can be used to cancel or check execution.
  • The scheduleAtFixedRate() and scheduleWithFixedDelay() methods create and execute tasks that run periodically until cancelled.
  • Zero and negative delays (but not periods) are also allowed in schedule methods, and are treated as requests for immediate execution.
  • All schedule methods accept relative delays and periods as arguments, not absolute times or dates.
  • To schedule at a certain future date, we can use the api in following manner – schedule(task, date.getTime() - System.currentTimeMillis(), TimeUnit.MILLISECONDS).
  • All methods return the ScheduledFuture object which is a delayed result-bearing action that can be cancelled.

2. ScheduledExecutorService Example

In this example, we will execute a simple task under various scenarios to better understand the usage of this interface.

class Task implements Callable<String> 
{
	private final String name;

	public Task(String name) {
		this.name = name;
	}

	@Override
	public String call() throws Exception {
		return "Task [" + name + "] executed on : " + LocalDateTime.now().toString();
	}
}

2.1. Execute a task at fixed delay

Java example to execute a task at fixed delay of 2 seconds using ScheduledExecutorService.

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public class Main 
{
	public static void main(String[] args) throws InterruptedException 
	{
		ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
		
		List<ScheduledFuture<String>> results = new ArrayList<ScheduledFuture<String>>();

		for (int i = 1; i <= 5; i++) 
		{
			Task task = new Task("Task-" + i);
			ScheduledFuture<String> result = executor.schedule(task, i*2, TimeUnit.SECONDS);
			results.add(result);
		}
		
		executor.shutdown();
		
		try { 
			executor.awaitTermination(1, TimeUnit.DAYS); 
			
			for(ScheduledFuture<String> result : results) {
				System.out.println(result.get());
			}
			
        } catch (Exception e) { 
        	e.printStackTrace(); 
        }
	}
}

Program output.

Task [Task-1] executed on : 2019-05-23T14:01:24.497
Task [Task-2] executed on : 2019-05-23T14:01:26.410
Task [Task-3] executed on : 2019-05-23T14:01:28.411
Task [Task-4] executed on : 2019-05-23T14:01:30.410
Task [Task-5] executed on : 2019-05-23T14:01:32.411

Task [Task-1] is SUCCESS !!
Task [Task-2] is SUCCESS !!
Task [Task-3] is SUCCESS !!
Task [Task-4] is SUCCESS !!
Task [Task-5] is SUCCESS !!

2.2. Execute a task at a given time

If we want to execute a task at a given time, calculate the difference between that planned date and the current date and use the difference as the delay of the task.

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public class Main 
{
	public static void main(String[] args) throws InterruptedException, ExecutionException 
	{
		ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
		
		LocalDateTime now = LocalDateTime.now();
	    LocalDateTime afterOneMinute = now.plusMinutes(1);
	 
	    Duration duration = Duration.between(now, afterOneMinute);

	    long delay = Math.abs(duration.toMillis());
	    
	    System.out.println("Task scheduled at : "+ LocalDateTime.now());
		
	    ScheduledFuture<String> result = executor.schedule(new Task("Task-1"), delay, TimeUnit.MILLISECONDS);
		
		executor.shutdown();
		
		executor.awaitTermination(1, TimeUnit.HOURS); 
		
		System.out.println(result.get());
	}
}

Program output.

Task scheduled at 			: 2019-05-23T14:21:59.627

Task [Task-1] executed on 	: 2019-05-23T14:22:59.632

Task [Task-1] is SUCCESS !!

Drop me your questions related to ScheduledExecutorService in comments.

Happy Learning !!

References :

ScheduledExecutorService Java Doc
ScheduledThreadPoolExecutor Java Doc

Was this post helpful?

Join 7000+ Fellow Programmers

Subscribe to get new post notifications, industry updates, best practices, and much more. Directly into your inbox, for free.

Leave a Comment

HowToDoInJava

A blog about Java and its related technologies, the best practices, algorithms, interview questions, scripting languages, and Python.