Signup/Sign In

Java Timer and TimerTask

A Timer in Java is used to schedule tasks. A TimerTask is a task that we want to perform. We can define a task with the help of TimerTask and schedule it using the Timer. The java.util.Timer class uses background threads for scheduling tasks.

The TimerTask, also part of java.util, is an abstract class that implements the Runnable interface. We need to override the run() method to define a task.

In this tutorial, we will learn how to schedule TimerTasks using a Timer.

Timer and TimerTask in Java

Scheduling a Task After a Delay

The schedule() method of the Timer class is used to schedule tasks in the future by using threads. This method takes a TimerTask instance and a delay after which we want to execute the task.

If we want to execute the task immediately, then we can pass zero as the second parameter. Note that the delay is in milliseconds.

import java.util.Timer;
import java.util.TimerTask;

public class Demo
{
	public static void main(String[] args)
	{
		TimerTask t = new TimerTask() {
			public void run()
			{
				System.out.println("Performing the task(takes 2000ms)");
				try {
					Thread.sleep(2000);
				} 
				catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("Task Completed");
			}
		};
		
		Timer timer = new Timer();
		timer.schedule(t, 1000);//Scheduling the task after a delay of 1000ms
	}
}


Performing the task(takes 2000ms)
Task Completed

We can also create a new class and extend the TimerTask class. Note that multiple TimerTasks can share a single Timer, as the Timer class is thread-safe and does not require any external synchronization.

Let's create two instances of our user-defined class and schedule them using a single Timer.

import java.util.Timer;
import java.util.TimerTask;

class AdditionTask extends TimerTask
{
	int a;
	int b;
	AdditionTask(int i, int j)
	{
		this.a = i;
		this.b = j;
	}

	@Override
	public void run()
	{
		System.out.println("Performing the Addition(takes 2000ms)");
		try {
			Thread.sleep(2000);
		} 
		catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("The sum is: " + (a+b));
	}	
}
public class Demo
{
	public static void main(String[] args)
	{
		AdditionTask t1 = new AdditionTask(10, 20);
		AdditionTask t2 = new AdditionTask(40, 60);
		Timer timer = new Timer();
		timer.schedule(t1, 0);//Scheduling the first task without any delay
		timer.schedule(t2, 5000);//Scheduling the second task after a delay of 5000ms
	}
}


Performing the Addition(takes 2000ms)
The sum is: 30
Performing the Addition(takes 2000ms)
The sum is: 100

Another thing to note is that our program will continue running even after the task is done. To terminate our program, we can use System.exit(0) in our run() method.

@Override
public void run()
{
	System.out.println("Performing the Addition(takes 2000ms)");
	try {
		Thread.sleep(2000);
	} 
	catch (InterruptedException e) {
		e.printStackTrace();
	}
	System.out.println("The sum is: " + (a+b));
	System.exit(0);
}

Scheduling a Task on a Date and Time

The schedule() method can take a Date object instead of the delay. The Timer will schedule the task on that date and time. The following code demonstrates this.

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

class AdditionTask extends TimerTask
{
	int a;
	int b;
	AdditionTask(int i, int j)
	{
		this.a = i;
		this.b = j;
	}

	@Override
	public void run()
	{
		System.out.println("Performing the task on: " + new Date());
		System.out.println("The sum is: " + (a+b));
	}	
}
public class Demo
{
	public static void main(String[] args)
	{
		Date date = new Date();
		System.out.println("Current Date: " + date);
		
		date.setTime(date.getTime() + 5000);//increasing the time by 5000ms
		
		AdditionTask t = new AdditionTask(10, 20);
		Timer timer = new Timer();
		timer.schedule(t, date);//Scheduling the task on the given date
	}
}


Current Date: Wed Aug 04 19:19:32 IST 2021
Performing the task on: Wed Aug 04 19:19:37 IST 2021
The sum is: 30

Scheduling a Repeatable Task

We can pass the third parameter to the schedule() method to repeat the task after a certain period. The third parameter denotes the time gap(in milliseconds) between the two occurrences of the task.

This time gap denotes a fixed delay after the occurrence of the previous task. The time gap is relative as it is calculated after the completion of the previous task.

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

class AdditionTask extends TimerTask
{
	int a;
	int b;
	AdditionTask(int i, int j)
	{
		this.a = i;
		this.b = j;
	}
	@Override
	public void run()
	{
		System.out.println("Performing the task on: " + new Date());
		System.out.println("The sum is: " + (a+b));
	}
}
public class Demo
{
	public static void main(String[] args)
	{
		AdditionTask t = new AdditionTask(10, 20);
		
		long delay = 100;
		long repeatPeriod = 1000;
		Timer timer = new Timer();
		timer.schedule(t, delay, repeatPeriod);//Repeat task every 1000ms
	}
}


Performing the task on: Thu Aug 05 08:55:19 IST 2021
The sum is: 30
Performing the task on: Thu Aug 05 08:55:20 IST 2021
The sum is: 30
Performing the task on: Thu Aug 05 08:55:21 IST 2021
The sum is: 30
Performing the task on: Thu Aug 05 08:55:22 IST 2021
The sum is: 30
Performing the task on: Thu Aug 05 08:55:23 IST 2021
The sum is: 30

We can also schedule a task at a fixed rate by using the scheduleAtFixedRate() method. This will use the absolute time to schedule the tasks. This method won't affect the rest of the tasks if one of them gets delayed.

In this case, the time gap is absolute and won't be affected by the completion time of the previous task.

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

class AdditionTask extends TimerTask
{
	int a;
	int b;
	AdditionTask(int i, int j)
	{
		this.a = i;
		this.b = j;
	}
	@Override
	public void run()
	{
		System.out.println("Performing the task on: " + new Date());
		System.out.println("The sum is: " + (a+b));
	}	
}
public class Demo
{
	public static void main(String[] args)
	{
		AdditionTask t = new AdditionTask(10, 20);
		
		long delay = 100;
		long repeatPeriod = 1000;
		Timer timer = new Timer();
		timer.scheduleAtFixedRate(t, delay, repeatPeriod);//Repeat task every 1000ms
	}
}


Performing the task on: Wed Aug 04 19:21:46 IST 2021
The sum is: 30
Performing the task on: Wed Aug 04 19:21:47 IST 2021
The sum is: 30
Performing the task on: Wed Aug 04 19:21:48 IST 2021
The sum is: 30
Performing the task on: Wed Aug 04 19:21:49 IST 2021
The sum is: 30
Performing the task on: Wed Aug 04 19:21:50 IST 2021
The sum is: 30
Performing the task on: Wed Aug 04 19:21:51 IST 2021
The sum is: 30

We can use these methods(with an appropriate repeat period) to perform a task every minute, every hour, every day, and so on.

Canceling Tasks

We can use the cancel() method in the run() method of our TimerTasks to cancel them after just a single execution.

In the code below, we have scheduled a task to be repeated every second. But because of the cancel() method, the task will execute just once.

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

class AdditionTask extends TimerTask
{
	int a;
	int b;
	AdditionTask(int i, int j)
	{
		this.a = i;
		this.b = j;
	}
	@Override
	public void run()
	{
		System.out.println("Performing the task on: " + new Date());
		System.out.println("The sum is: " + (a+b));
		cancel();//cancel after one execution
	}	
}
public class Demo
{
	public static void main(String[] args)
	{
		AdditionTask t = new AdditionTask(10, 20);

		Timer timer = new Timer();
		timer.scheduleAtFixedRate(t, 1000, 1000);//Repeat task every 1000ms
	}
}


Performing the task on: Wed Aug 04 19:24:10 IST 2021
The sum is: 30

We can also use the Timer.cancel() method to cancel a scheduled task. We can make the thread sleep for a few seconds to execute the task at least once.

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

class AdditionTask extends TimerTask
{
	int a;
	int b;
	AdditionTask(int i, int j)
	{
		this.a = i;
		this.b = j;
	}
	@Override
	public void run()
	{
		System.out.println("Performing the task on: " + new Date());
		System.out.println("The sum is: " + (a+b));
	}	
}
public class Demo
{
	public static void main(String[] args) throws InterruptedException
	{
		AdditionTask t = new AdditionTask(10, 20);

		Timer timer = new Timer();
		timer.scheduleAtFixedRate(t, 0, 1000);//Start after a delay of 1000 and Repeat task every 1000ms
		Thread.sleep(1);
		timer.cancel();//Canceling the timer
	}
}


Performing the task on: Wed Aug 04 19:26:44 IST 2021
The sum is: 30

ExecutorService

We can also use the ExecutorService to schedule TimerTasks.

import java.util.Date;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

class AdditionTask extends TimerTask
{
	int a;
	int b;
	AdditionTask(int i, int j)
	{
		this.a = i;
		this.b = j;
	}

	@Override
	public void run()
	{
		System.out.println("Performing the task on: " + new Date());
		System.out.println("The sum is: " + (a+b));
	}	
}
public class Demo
{
	public static void main(String[] args) throws InterruptedException
	{
		AdditionTask at = new AdditionTask(10, 20);
		
	    long delay  = 1;
	    long repeatPeriod = 2;
	    
	    ScheduledExecutorService exe = Executors.newSingleThreadScheduledExecutor();
	    exe.scheduleAtFixedRate(at, delay, repeatPeriod, TimeUnit.SECONDS);
	}
}


Performing the task on: Wed Aug 04 19:33:21 IST 2021
The sum is: 30
Performing the task on: Wed Aug 04 19:33:23 IST 2021
The sum is: 30
Performing the task on: Wed Aug 04 19:33:25 IST 2021
The sum is: 30
Performing the task on: Wed Aug 04 19:33:27 IST 2021
The sum is: 30
Performing the task on: Wed Aug 04 19:33:29 IST 2021
The sum is: 30

They are pretty similar to the Timer class but have a few significant differences. The following points summarize the key differences between a Timer and an ExecutorService.

  • Timers are affected by changes in the system clock, but ExecutorService is not influenced.
  • A Timer can only have a single thread, but the ExecutorService can use multiple threads.
  • A runtime exception in the Timer thread will cancel all the remaining tasks. Exceptions won't affect the ExecutorService.

Summary

TimerTasks are scheduled by using the Timer class. The Timer class contains overloaded schedule() methods to schedule tasks. We can also use the schedule() method to repeat tasks after certain time intervals. The overloaded schedule() methods discussed in this tutorial are summarized below.

  • The schedule(TimerTask t, long delay) is used to schedule the task after a delay.
  • The schedule(TimerTask t, Date d) is used to schedule the task on a certain date and time.
  • The schedule(TimerTask t, long delay, long repeatPeriod) is used to schedule a repeatable task after an initial delay. The task is repeated after the repeatPeriod.
  • The schedule(TimerTask t, Date d, long repeatPeriod) will repeat the task after the repeatPeriod, but the task will start on the mentioned date.


About the author:
I am a 3rd-year Computer Science Engineering student at Vellore Institute of Technology. I like to play around with new technologies and love to code.