Scheduling tasks in Java with TimerTask

Image by Timisu from pixabay.com

Want to make sure your daily backups are running? Take a look at PushMon, the easiest way to monitor your cron and scheduled tasks.

Introduction

The use of scheduled tasks is very common in large and medium-sized systems, mainly because they have several functionalities linked to the automation of tasks without human intervention. It is common to see the use of tools like crontab (Linux) for scheduling tasks, be they in Java or another language.

Task Schedulers: TimerTask

The Java language natively already has a task scheduler that can be exploited through the TimerTask class.
The TimerTask class is an abstract class that implements the Runnable interface, used when we need to work with multi-thread, as shown in Listing 1.

package java.util;
  
public abstract class TimerTask implements Runnable {
  
    final Object lock = new Object();
    int state = VIRGIN;
    static final int VIRGIN = 0;
    static final int SCHEDULED   = 1;
    static final int EXECUTED    = 2;
    static final int CANCELLED   = 3;
    long nextExecutionTime;
    long period = 0;
  
    protected TimerTask() {
    }
  
    public abstract void run();
  
    public boolean cancel() {
        synchronized(lock) {
            boolean result = (state == SCHEDULED);
            state = CANCELLED;
            return result;
        }
    }
  
    public long scheduledExecutionTime() {
        synchronized(lock) {
            return (period < 0 ? nextExecutionTime + period
                               : nextExecutionTime - period);
        }
    }
}

The method that interests us in the above listing is the “public abstract void run ()”, it will be responsible for executing our logic at preconfigured intervals. As you may have already noticed the principle for using the TimeTask class is to extend it and implement the run () method, since this is abstract and its implementation is mandatory. So that’s exactly what we’re going to do, as shown in Listing 2.

Listing 2. Extending the TimerTask class

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

public class Scheduler extends TimerTask {

   Date instanteAtual;

   @Override
   public void run() {
      instanteAtual = new Date();
      System.out.println(instanteAtual);
   }
}
The above example is simple only for didactic purposes. Our Scheduler class extends the TimerTask class by implementing a logic within the run() method, which is to show the current instant at which it is running. For a first time this example is useful to see how TimerTask works.

Now we need to start our Scheduler class, otherwise the run() method will never be called, as shown in Listing 3.
Listing 3. Starting our TimerTask
public class StartScheduler {

   public static void main(String[] args) {
      Timer timer = new Timer();
      Scheculer scheduler = new Scheduler();
      timer.schedule(scheduler, 0, 1000);
      while(true){
         System.out.println("execution alert ...");
         try {
            Thread.sleep(2000);
         } 
         catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }
}
We instantiate the Timer object, which is responsible for starting our Scheduler:
Timer timer = new Timer();
We then instantiate our scheduler class by assigning its instance to the “scheduler” object.
Scheduler scheduler = new Scheduler();
Now use the timer object to call the schedule() method that actually starts the execution of our scheduler thread. The schedule() method we use has the following signature:
public void schedule(TimerTask task, long delay, long period)
It receives a TimerTask object, which in our case is the Scheduler class, a value of type “long” with time in milliseconds before the thread starts to run, and finally a value also of type “long” with the interval of time in milliseconds for repeated thread execution, that is, how long it will run.

timer.schedule(scheduler, 0, 1000);

That tells us that our task will be executed one at a time without delay to start, that is, as soon as this line is executed the task will be initialized immediately.

Conclusion

For many cases, TimerTask is an incredible tool that helps solve problems that would need a whole technological infrastructure to be solved, so we do not become “slaves” of tools external to Java, bringing everything needed into a single place, performing a true “inbox”, all in one place.

But there are even more specific cases that require a greater level of control and detail. Of course this is possible with TimerTask however the work would be a bit more arduous and maybe even unnecessary since we already have API’s ready for such a task, as is the case with the Quartz Scheduler.
In the next post we will detail the Quartz Scheduler.