Java Timer

Java Timer

0 Comments

Last Updated on June 30, 2019 by Simanta

Timer is a utility class as a facility for Threads to schedule tasks for future execution as a background thread. You can use this class to schedule tasks for one-time execution or for repeated execution at a regular interval.

In this post, I’ll explain how to schedule tasks in Java applications using the Timer and TimerTask classes.

Timer and TimerTask

Timer
Timer is used with
TimerTask
TimerTask, an abstract class which defines the task to be scheduled by
Timer
Timer. You need to extend
TimerTask
TimerTask to create a task that will be scheduled by
Timer
Timer. Java
TimerTask
TimerTask implements the
Runnable
Runnable interface.

Each of the

TimerTask
TimerTask is executed sequentially by a
Timer
Timer object which has a corresponding single background thread.
TimerTask
TimerTask objects should complete execution quickly. If a timer task takes too long to complete, it dominates the timer’s task execution thread, which in turn will delay the execution of the subsequent tasks. The tasks will finally accumulate into a queue.

Note: Java

Timer
Timer object can be shared by multiple threads without any external synchronization.

A

TimerTask
TimerTask object remains in one of the following states.

  • VIRGIN
    VIRGIN: When a task is created, its initial state will be
    VIRGIN
    VIRGIN
  • SCHEDULED
    SCHEDULED: Once the task is picked up by
    Timer
    Timer for execution, its state is changed to
    SCHEDULED
    SCHEDULED.
  • EXECUTED
    EXECUTED: After execution its state becomes
    EXECUTED
    EXECUTED.
  • CANCELLED
    CANCELLED: If we call the
    cancel()
    cancel() method on a task, the task goes into the
    CANCELLED
    CANCELLED state. A task in the
    CANCELLED
    CANCELLED state will never be picked up by the
    Timer
    Timer for execution.

Scheduling Tasks with Timer

Let’s start coding and use

Timer
Timer to schedule a
TimerTask
TimerTask.

MyTask
MyTask is a Java class that defines its own task by extending
TimerTask
TimerTask.

MyTask.java
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
package springframework.guru.javatimer.task;
import java.util.Date;
import java.util.TimerTask;
public class MyTask extends TimerTask {
@Override
public void run() {
System.out.println("Start of mytask at " + new Date());
timeConsumingTask();
System.out.println("End of mytask at " + new Date());
}
public void timeConsumingTask() {
try {
Thread.sleep(20000);
}catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
package springframework.guru.javatimer.task; import java.util.Date; import java.util.TimerTask; public class MyTask extends TimerTask { @Override public void run() { System.out.println("Start of mytask at " + new Date()); timeConsumingTask(); System.out.println("End of mytask at " + new Date()); } public void timeConsumingTask() { try { Thread.sleep(20000); }catch (InterruptedException ex) { ex.printStackTrace(); } } }
package springframework.guru.javatimer.task;

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

public class MyTask extends TimerTask {
   @Override
   public void run() {
       System.out.println("Start of mytask at " + new Date());
       timeConsumingTask();
       System.out.println("End of mytask at " + new Date());
   }
   public void timeConsumingTask() {
       try {
           Thread.sleep(20000);
       }catch (InterruptedException ex) {
           ex.printStackTrace();
       }
   }
}

To define your own

TimerTask
TimerTask you need to override the
run()
run() method of
TimerTask
TimerTask. Here we have assumed that the task will take 20 seconds to complete.

Next we will schedule the defined task.

Scheduling a Task to Run Once

I have written a JUnit test class to run the task we defined with the help of

Timer
Timer. If you are new to JUnit, I suggest going through my series of JUnit posts.

The

MyTaskTest
MyTaskTest class is this.

MyTaskTest.java

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
package springframework.guru.javatimer.task;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.Date;
import java.util.Timer;
public class MyTaskTest {
MyTask myTask;
Timer timer;
@Before
public void setUp() {
myTask = new MyTask();
timer = new Timer(true);
}
@After
public void tearDown() {
myTask = null;
timer = null;
}
@Test
public void schedulingTaskOnce() {
long delay = 1000L;
timer.schedule(myTask, delay*10);
System.out.println("MyTask begins!!" + new Date());
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package springframework.guru.javatimer.task; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.util.Date; import java.util.Timer; public class MyTaskTest { MyTask myTask; Timer timer; @Before public void setUp() { myTask = new MyTask(); timer = new Timer(true); } @After public void tearDown() { myTask = null; timer = null; } @Test public void schedulingTaskOnce() { long delay = 1000L; timer.schedule(myTask, delay*10); System.out.println("MyTask begins!!" + new Date()); try { Thread.sleep(60000); } catch (InterruptedException e) { e.printStackTrace(); } } }
package springframework.guru.javatimer.task;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

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

public class MyTaskTest {
   MyTask myTask;
   Timer timer;

   @Before
   public void setUp() {
       myTask = new MyTask();
       timer = new Timer(true);
   }

   @After
   public void tearDown() {
       myTask = null;
       timer = null;
   }

   @Test
   public void schedulingTaskOnce() {
       long delay = 1000L;
       timer.schedule(myTask, delay*10);
       System.out.println("MyTask begins!!" + new Date());
       try {
           Thread.sleep(60000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
   }
}

In the

@Setup
@Setup method,
Timer(true)
Timer(true) creates a new
Timer
Timer whose associated thread can be run as a daemon thread. You can also use the overladed
Timer(String name)
Timer(String name) constructor to create a timer whose thread has the specified name.

In the test case, the

timer.schedule()
timer.schedule() method schedules the
TimerTask
TimerTask to execute after a delay of
10,000
10,000 ms.

Once the timer schedules the task, the code instructs the timer’s thread to sleep for

60
60 seconds.

The output on running the tests in IntelliJ is this.
Test Output Scheduling Once

Scheduling a Repeated Task on a Regular Interval

You can use the

scheduleAtFixedRate()
scheduleAtFixedRate() method of
Timer
Timer to schedule the
TimerTask
TimerTask periodically with a specific interval.

This code snippet schedules the task with a delay of

1000
1000 ms and to repeat after every
500
500 ms.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@Test
public void schedulingTaskAtRepeatedInterval() {
long delay = 1000L;
long period = 1000L;
timer.scheduleAtFixedRate(myTask, delay, period);
System.out.println("MyTask begins and repeats at a specific interval!!" + new Date());
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Test public void schedulingTaskAtRepeatedInterval() { long delay = 1000L; long period = 1000L; timer.scheduleAtFixedRate(myTask, delay, period); System.out.println("MyTask begins and repeats at a specific interval!!" + new Date()); try { Thread.sleep(60000); } catch (InterruptedException e) { e.printStackTrace(); } }
@Test
   public void schedulingTaskAtRepeatedInterval() {
       long delay = 1000L;
       long period = 1000L;
       timer.scheduleAtFixedRate(myTask, delay, period);
       System.out.println("MyTask begins and repeats at a specific interval!!" + new Date());
       try {
           Thread.sleep(60000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
   }

The output on running the tests in IntelliJ is this.

Scheduling a Task to Run Once a Day

Consider you need to schedule a task to run once a day. One approach is to call the

scheduleAtFixedRate()
scheduleAtFixedRate() method passing the appropriate delay and period parameters like this.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@Test
public void schedulingTaskDaily() {
long delay = 1000L;
long period = 1000L * 60L * 60L * 24L;
timer.scheduleAtFixedRate(myTask, delay, period);
System.out.println("MyTask begins and repeats every day!!" + new Date());
try {
Thread.sleep(30000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Test public void schedulingTaskDaily() { long delay = 1000L; long period = 1000L * 60L * 60L * 24L; timer.scheduleAtFixedRate(myTask, delay, period); System.out.println("MyTask begins and repeats every day!!" + new Date()); try { Thread.sleep(30000); } catch (InterruptedException e) { e.printStackTrace(); } }
@Test
public void schedulingTaskDaily() {
   long delay = 1000L;
   long period = 1000L * 60L * 60L * 24L;
   timer.scheduleAtFixedRate(myTask, delay, period);
   System.out.println("MyTask begins and repeats every day!!" + new Date());
   try {
       Thread.sleep(30000);
   } catch (InterruptedException e) {
       e.printStackTrace();
   }
}

The output on running the test in IntelliJ is this.

Another approach is to use the

Timer.schedule(TimerTask task, Date firstTime, long period)
Timer.schedule(TimerTask task, Date firstTime, long period) method.

Cancelling Timer and TimerTask

At times you might need to cancel a running

TimerTask
TimerTask. One way is to invoke the
cancel()
cancel() method on the timer. The second way is to call the
cancel()
cancel() method on the thread that runs the
TimerTask
TimerTask.

Call

cancel()
cancel() on the
Timer
Timer if that’s all it is doing. On the other hand, if the timer itself has other tasks which you wish to continue, call the
cancel()
cancel() method on the thread running
TimerTask
TimerTask like this.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public void run() {
System.out.println("Start of mytask at " + new Date());
timeConsumingTask();
System.out.println("End of mytask at " + new Date());
cancel();
}
public void run() { System.out.println("Start of mytask at " + new Date()); timeConsumingTask(); System.out.println("End of mytask at " + new Date()); cancel(); }
public void run() {
   System.out.println("Start of mytask at " + new Date());
   timeConsumingTask();
   System.out.println("End of mytask at " + new Date());
   cancel();
}

The test code is this:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@Test
public void checkCancelOfTimerTask() {
long delay = 1000L;
long period = 1000L;
timer.scheduleAtFixedRate(myTask, delay, period);
System.out.println("MyTask begins and repeats at a specific interval and then cancels!!" + new Date());
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Test public void checkCancelOfTimerTask() { long delay = 1000L; long period = 1000L; timer.scheduleAtFixedRate(myTask, delay, period); System.out.println("MyTask begins and repeats at a specific interval and then cancels!!" + new Date()); try { Thread.sleep(60000); } catch (InterruptedException e) { e.printStackTrace(); } }
@Test
public void checkCancelOfTimerTask() {
   long delay = 1000L;
   long period = 1000L;
   timer.scheduleAtFixedRate(myTask, delay, period);
   System.out.println("MyTask begins and repeats at a specific interval and then cancels!!" + new Date());
   try {
       Thread.sleep(60000);
   } catch (InterruptedException e) {
       e.printStackTrace();
   }
}

The output on running the tests in IntelliJ is this.

Note that when you call the

cancel()
cancel() method within the
run()
run() method of a
TimerTask
TimerTask that was invoked by this
Timer
Timer, it guarantees that the ongoing task will be the last task executed by the
Timer
Timer. It takes a minute and above to terminate the test since we have given
60
60 seconds to stop the
Timer
Timer thread.

On the other hand, the

cancel()
cancel() method on
Timer
Timer terminates the timer discarding any currently scheduled tasks. The executing thread terminates once the timer is terminated and no more tasks can be scheduled on the cancelled timer.

The test code for calling

cancel()
cancel() on the
Timer
Timer is this.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@Test
public void checkCancelOnTimerObject() {
long delay = 1000L;
long period = 1000L;
timer.scheduleAtFixedRate(myTask, delay, period);
System.out.println("MyTask begins and repeats at a specific interval!!" + new Date());
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
timer.cancel();
System.out.println("Timer cancelled");
}
@Test public void checkCancelOnTimerObject() { long delay = 1000L; long period = 1000L; timer.scheduleAtFixedRate(myTask, delay, period); System.out.println("MyTask begins and repeats at a specific interval!!" + new Date()); try { Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } timer.cancel(); System.out.println("Timer cancelled"); }
@Test
public void checkCancelOnTimerObject() {
   long delay = 1000L;
   long period = 1000L;
   timer.scheduleAtFixedRate(myTask, delay, period);
   System.out.println("MyTask begins and repeats at a specific interval!!" + new Date());
   try {
       Thread.sleep(4000);
   } catch (InterruptedException e) {
       e.printStackTrace();
   }
   timer.cancel();
   System.out.println("Timer cancelled");
}

Here we specify the sleep time for the

Timer
Timer thread because we are running the code snippet as a JUnit test case. Hence we must call
Thread.Sleep(delay*n)
Thread.Sleep(delay*n) to allow the Timer’s thread to run the task before the JUnit test stops executing.

Let us change the sleep time of

MyTask
MyTask to
1
1 second to check if the timer is cancelled.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public void timeConsumingTask() {
try {
Thread.sleep(1000);
}catch (InterruptedException ex) {
ex.printStackTrace();
}
}
public void timeConsumingTask() { try { Thread.sleep(1000); }catch (InterruptedException ex) { ex.printStackTrace(); } }
public void timeConsumingTask() {
  try {
      Thread.sleep(1000);
  }catch (InterruptedException ex) {
      ex.printStackTrace();
  }
}

The output on running the tests in IntelliJ is this.

Summary

The built-in Timer is adequate for scheduling tasks in small to mid-size Java applications. When you are developing Spring applications, you can also use the

TaskExecutor
TaskExecutor and
TaskScheduler
TaskScheduler interfaces that the Spring Framework brings in.

However, for large-scale enterprise application development using Spring Boot, you need a more comprehensive scheduling solution.

Quartz is one open source job scheduling library with rich enterprise-class features including JTA transactions and clustering. Spring Boot provides the

spring-boot-starter-quartz
spring-boot-starter-quartz “Starter” to get you quickly up and running with Quartz.

About SFG Contributor

Staff writer account for Spring Framework Guru

    You May Also Like

    Leave a Reply

    Your email address will not be published. Required fields are marked *

    This site uses Akismet to reduce spam. Learn how your comment data is processed.