Timers vs Handlers

ABHIJIT KUMAR
6 min readSep 7, 2019

--

An application often requires repeating certain tasks on a periodic basis or after a certain interval. This functionality can be used for polling new data from the network, running manual animations, or simply updating the UI. These are four common ways to achieve the same:

  1. Handler — Execute a Runnable task on the UI Thread after an optional delay.
  2. ScheduledThreadPoolExecutor — Execute periodic tasks with a background thread pool
  3. AlarmManager — Execute any periodic task in the background as a service
  4. TimerTask — Doesn’t run in UIThread and is not reliable. Consensus is to never use TimerTask

I’ll be discussing Timers and Handlers in this blog as they are widely into practice and will also be discovering how Handlers are a better option.

We’ll be starting off with some basic definitions to ensure utmost clarity on the concepts to follow. If you have used timers sometime and are confident enough of their usage, I advice you too to lightly browse through.

What really is a Timer ?

Timer in Java is a utility class which is used to schedule tasks for both one time and repeated execution. Didn’t get the complex terminology ? Don’t worry, the forthcoming example will help you. A Timer can be imagined as your phone’s alarm which you use to schedule some one time alarms to remind you of an occasional meetup as well as some regular repeated alarms to wake you up each morning.

How do we use a Timer ?

There are two classes : java.util.Timer & java.util.TimerTask which are used to schedule tasks. As waking up is the task which needs to be executed and the time when it is to be done is determined by the alarm, TimerTask is the actual task which is to be executed and when that needs to be done is determined by the Timer.

The Timer class requires that the application code extends TimerTask class to run the task. The TimerTask, in turn, implements the Runnable interface. Here is a simple class which extends the TimerTask. You just have to define the run() method to do whatever you want.

import java.util.Timer;
import java.util.TimerTask;
public class TimerTaskExample {
Timer timer; //creating a variable named timer of type Timer
public TimerTaskExample(int seconds) {
timer = new Timer(); //creating an instance of the timer class
timer.schedule(new Reminder(), seconds * 1000);
}
class Reminder extends TimerTask {
public void run() {
System.out.println("Timer Task Executed..");
timer.cancel(); // Terminate the timer thread
}
}
public static void main(String args[]) {
new TimerTaskExample(5);
System.out.println("Task scheduled..Hang on for 5 secs...");
}
}

Output of the above code :

Task scheduled..Hang on for 5 secs...Timer Task Executed..    //appears after 5 seconds

How to do this on Repeat ?

import java.util.Timer;
import java.util.TimerTask;
public class TimerTaskExample {
Timer timer;
public TimerTaskExample(int seconds) {
timer = new Timer();
timer.schedule(new Reminder(), 0, // initial delay
seconds * 1000); // subsequent rate
}
class Reminder extends TimerTask {
int loop = 5;
public void run() {
if (loop > 0) {
System.out.println("Knock Knock..!");
loop--;
}
else {
System.out.println("That's it.. Done..!");
timer.cancel();
}
}
} public static void main(String args[]) {
new TimerTaskExample(1);
System.out.format("Task scheduled..!");
}
}

Output of the above code:

Task scheduled..!Knock Knock..!  //after 1 second from the startKnock Knock..!  //after 2 seconds from the startKnock Knock..!  //after 3 seconds from the startKnock Knock..!  //after 4 seconds from the startKnock Knock..!  //after 5 seconds from the startThat's it.. Done..!

A program keeps on executing as long as its timer threads keep running. A timer thread can be terminated in four ways :

  • Calling cancel on the timer. We can do this from anywhere in the program, but we prefer doing it from a timer task’s run method to ensure the desired timer is cancelled in case other timers are running as well.
  • Making the timer’s thread a “daemon” by creating the timer like this: new Timer(true). If the only threads left in the program are daemon threads, the program exits.
  • After all the timer’s scheduled tasks have finished executing, remove all references to the Timer object. Eventually, the timer’s thread will terminate.
  • Invoke the System.exit method, which makes the entire program (and all its threads) exit.

As the first method is widely in practice, let us dive a bit deeper into the functionality of the cancel function. When you call the cancel function on a timer it results in the following actions :

  1. Timer won’t cancel any currently executing task.
  2. Timer would discard other scheduled tasks and won’t execute them.
  3. Once current task being executed completes, the timer thread will terminate.
  4. If you call timer.cancel more than once, the second and forthcoming calls will be ignored.

Point to be noted : Both Timer and TimerTask provide cancel() method. Timer’s cancel() method cancels whole timer while TimerTask’s one cancels only a particular task. So always be careful while calling the cancel function predicting your use cases or you could end up in unexpected behaviour of the tasks.

The Real Problem

Well, after writing Android code for quite a while, I noticed somethings which work quite differently from usual Java. Timer is one of them.

When we use a Timer, a new thread is introduced in the application for a very minor reason. When we think in terms of mobile applications, it often calls for reconsidering choices we might make differently for desktop applications with relatively richer resources at their disposal. Many a times debuggers find the timers functioning properly(as revealed by the debug points) but the tasks linked with them fail to execute at times unexpectedly(tasks which include UI updation depending on timer are common use cases to observe this behaviour). Their execution cannot be relied upon which is very crucial to product based startups. You can see such an example here

The solution to this problem is doing it the Android way: Using a Handler.

How do we use a Handler?

A Handler is used to run code on a given thread after a delay or repeat tasks periodically on a thread. This is done by constructing a Handler and then "posting" Runnable code to the event message queue on the thread to be processed.

import android.os.Handler; // We need to import this Handler package

Handler handler = new Handler();
//creates handler object on main thread

private Runnable runTask = new Runnable() {
@Override
public void run() {
// Execute tasks on main thread
Log.d("Handlers", "Called on main thread");
}
};
// Run above code block on main thread after 2 seconds
handler.postDelayed(runTask, 2000);

How to do this on Repeat ?

import android.os.Handler;

Handler handler = new Handler();

private Runnable runTask = new Runnable() {
@Override
public void run() {
// Execute tasks on main thread
Log.d("Handlers", "Called on main thread");
// Repeat this task again another 2 seconds
handler.postDelayed(this, 2000);
}
};
// Start the initial runnable task by posting through the handler
handler.post(runTask);

We can remove the scheduled execution of a runnable with:

// Removes pending code execution
handler.removeCallbacks(runTask);

Advantages :

1. With a Handler, the Runnable executes in UIThread by default so we can safely update the user interface within the runnable code block.

2. Handlers run the task as a part of your main thread, avoiding the overhead of a second thread and also making for easy access to the View hierarchy used for the user interface. We just need to keep such tasks small and light to avoid slowing down the user experience.

3. You don’t have to create new Timer(Task)s all the time and can reuse the one Handler and Runnable.

Asynchronous task management using timers is easy for background processing in Android apps, without worrying too much about the low-level details(threads, message loops etc). They provide callback methods that help to schedule tasks and also to easily update the UI whenever required.

However, it is important to note that when using timers, a developer is submitting to its limitations, which resulted because of the design decisions that the author of the class took. There is also a limit to the number of jobs that can be scheduled using AsyncTasks.

Handler is more transparent of the two and probably gives you more freedom; so if you want more control on things you would choose Handler.

Thank you for spending part of your useful time reading this. Hope this helps moulding your developer life !

--

--