Timer

Java Timer example

In this example, we will learn about the Timer class available under the java.util package.

The Timer facilitates the execution of tasks in a background thread. The tasks to be executed by the Timer can be chosen either to be a one-time execution OR a repeated execution at pre-defined intervals.

Along with the mentioned execution frequency of the task, the scheduling time / delay of these tasks can also be optionally mentioned to the Timer class.

Representing what is stated above, the TimerTask to be executed can be:

  1. One-time execution which in turn can be:
    • Scheduled immediately
    • Scheduled to start after a delay
  2. Repeated execution at regular intervals which in turn can be:
    • Scheduled immediately
    • Scheduled to start after a delay

Components of Timer

We would briefly look at the internal components of the Timer class. In terms of usage, one only needs to create Tasks by extending the TimerTask and schedule them with the Timer instance.

The other two internal components – TaskQueue and TimerThread have been mentioned below for information purpose, so as to help one evaluate when and for what kind of tasks should the Timer class be used.

  1. Task Queue

  2. Internally, the Timer uses the TaskQueue as a “priority” queue maintaining tasks in the order of next execution. The priority queue holds task in the sequence they should be executed by the TimerThread.

  3. Timer Thread

  4. The TimerThread is a thread helper class which repeatedly monitors the TaskQueue and “sequentially” executes the tasks based on their execution order and time of execution. To note here, the Timer has only one instance of the TimerThread internally. Thus, if any of the scheduled Timer tasks takes excessive time to run, the other tasks scheduled for execution will keep waiting till the offending task completes. The waiting tasks may then be executed in rapid successions by the TimerThread causing unexpected results.

  5. Timer Task

  6. The TimerTask is the actual unit of task that needs to be performed by the Timer for either once or multiple times at regular intervals. The TimerTask is an abstract class implementing Runnable. As a user of the Timer, one needs to extend this class and implement the run method by providing the logic of the task that needs to be performed.

Now, let us look at an example using the Timer. In the example, we create two TimerTask:

  1. A TimerTask in a slave node which sends some heart-beat information at an interval of 10 seconds. The task is scheduled to start with a delay of 1 second.
  2. A TimerTask which updates the status being sent by the first task to AMBER. This task is executed once after a delay of 30 seconds.

Let’s look at TimerTask #1, TimerTaskSendHeartBeat for heartbeat sending.

class TimerTaskSendHeartBeat extends TimerTask {

	TimerExample healthStatusHolder = null;

	public TimerTaskSendHeartBeat(TimerExample healthStatusHolder) {
		this.healthStatusHolder = healthStatusHolder;
	}

	HeartBeatMessage message = null;

	@Override
	public void run() {

		// create HeartBeat message by getting Health Status (RED/GREEN/AMBER)
		// Error Code, if any AND time at which heartbeat is sent to help
		// receiver discard any delayed messages due to latency
		message = new HeartBeatMessage(
				this.healthStatusHolder.getHealthStatus(), Calendar
						.getInstance().getTimeInMillis(), -1);

		System.out.println("Sending HeartBeat Message");

		// Send the message to Monitoring Dashboard
		System.out.println(message);

		System.out.println("HeartBeat Message Sent");
	}

	/**
	 * Simple POJO which is a heartbeat message object It can have any decoder
	 * encoder mechanism to send over any messaging platform
	 */
	class HeartBeatMessage {
		private String status;
		private long heartBeatTime;
		private int errorCode;

		public HeartBeatMessage(String status, long heartBeatTime, int errorCode) {
			this.status = status;
			this.heartBeatTime = heartBeatTime;
			this.errorCode = errorCode;
		}

		public String getStatus() {
			return status;
		}

		public long getHeartBeatTime() {
			return heartBeatTime;
		}

		public int getErrorCode() {
			return errorCode;
		}

		@Override
		public String toString() {
			return "status: " + status + " timeOfHeartBeat: "
					+ new java.util.Date(this.heartBeatTime) + " errCode : "
					+ this.errorCode;
		}
	}

Below is the implementation of the TimerTask # 2, TimerTaskUpdateHeartBeat which just updates the status of the heartbeat message being sent.

class TimerTaskUpdateHeartBeat extends TimerTask {

	TimerExample healthClass = null;

	public TimerTaskUpdateHeartBeat(TimerExample healthClass) {
		this.healthClass = healthClass;
	}

	@Override
	public void run() {
		System.out.println("Task 2:: 30 seconds completed :: Updating health "
				+ "status to AMBER");
		healthClass.setHealthStatus("AMBER");
	}

}

Once both the TimerTask have been created, let us know schedule the tasks at the desired time and frequency of execution. This would require creating a new Timer instance and scheduling tasks to it.

public class TimerExample {
	private String healthStatus = "GREEN";

	public static void main(String[] args) {

		TimerExample example = new TimerExample();
		example.setHealthStatus("GREEN");

		// Create the Timer object
		Timer timer = new Timer("JCG Timer Example");

		// Create Timer task created to send heartBeats
		TimerTask taskToExecute = new TimerTaskSendHeartBeat(example);
		// schedule the task to start executing after 1 second
		// and re-execute every 10 seconds
		timer.scheduleAtFixedRate(taskToExecute, 1000, 10000);

		// Create Timer task to setHeartBeatStatus
		TimerTask setHeartBeatStatus = new TimerTaskUpdateHeartBeat(example);
		// schedule the task to start immediately but execute
		// first time after 30 seconds
		timer.schedule(setHeartBeatStatus, 30000);

		// Wait for 60 seconds and then cancel the timer cleanly
		try {
			Thread.sleep(60000);
		} catch (InterruptedException e) {
		}
		System.out.println("Cancelling Timer Cleanly after 60 seconds");
		timer.cancel();
	}

	/**
	 * Get Heartbeat Status of the application, could be GREEN / AMBER / RED
	 * based on any exceptions or service health
	 * 
	 * @return String
	 */
	public String getHealthStatus() {
		return this.healthStatus;
	}

	/**
	 * Set the status for the application could be GREEN / AMBER / RED
	 * 
	 * @param healthStatus
	 */
	public void setHealthStatus(String healthStatus) {
		this.healthStatus = healthStatus;
	}
}

On execution of the program, the output looks as below:

Sending HeartBeat Message
status: GREEN timeOfHeartBeat: Mon Jun 16 23:52:04 IST 2014 errCode : -1
HeartBeat Message Sent
Sending HeartBeat Message
status: GREEN timeOfHeartBeat: Mon Jun 16 23:52:14 IST 2014 errCode : -1
HeartBeat Message Sent
Sending HeartBeat Message
status: GREEN timeOfHeartBeat: Mon Jun 16 23:52:24 IST 2014 errCode : -1
HeartBeat Message Sent
Task 2:: 30 seconds completed :: Updating health status to AMBER
Sending HeartBeat Message
status: AMBER timeOfHeartBeat: Mon Jun 16 23:52:34 IST 2014 errCode : -1
HeartBeat Message Sent
Sending HeartBeat Message
status: AMBER timeOfHeartBeat: Mon Jun 16 23:52:44 IST 2014 errCode : -1
HeartBeat Message Sent
Sending HeartBeat Message
status: AMBER timeOfHeartBeat: Mon Jun 16 23:52:54 IST 2014 errCode : -1
HeartBeat Message Sent
Cancelling Timer Cleanly after 60 seconds

As seen from output above, the Timer is cancelled using the cancel method which ensures that any TimerTask being executed is completed before the Timer is cleaned up.

Other Points about Timer

  • The Timer instance created can be instructed to start the TaskThread as a Daemon Thread, in case the thread should no longer exist if there are no non-daemon threads remaining in the VM.
  • The Timer is thread-safe and is internally synchronized.
  • Java 5.0 introduced the ScheduledThreadPoolExecutor which is a thread pool for repeatedly executing tasks at a given rate or delay. It allows multiple service threads and accepts various time units. Thus, as the Timer has one single task execution thread (highlighted above), the ScheduledThreadPoolExecutor can have multiple threads executing/dedicated to task execution, in turn preventing one faulty task causing other tasks to be waiting for thread resource for execution.

The source code is available for download here.

Vishal Rajpal

Vishal enjoys designing and developing small and mid-sized Enterprise solutions in Java and it's ecosystem. He has graduated from RGTU, India in Electronics and Telecommunication Engineering. Currently, Vishal is working with an Analytics organization, enabling the in-house analytics as well as client teams to use technology as a differentiator for projects / problems related to Big Data.
Subscribe
Notify of
guest

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

0 Comments
Inline Feedbacks
View all comments
Back to top button