Java timing tasks: the java Timer class is used to implement the function of timing tasks

  • 2020-05-17 05:33:32
  • OfStack

1. An overview of the

In java, the function of regularly executing tasks is implemented, mainly using two classes, Timer and TimerTask. Among them, Timer is used to execute the specified tasks in a background thread according to the specified schedule.

TimerTask1 is an abstract class whose subclasses represent a task that can be planned by Timer, and the specific code to execute is written in the run method that TimerTask needs to be implemented.

Let's look at one of the simplest examples

Let's do that in code


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

public class TimerDemo {
  public static String getCurrentTime() {
    Date date = new Date();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    return sdf.format(date);
  }

  public static void main(String[] args) throws InterruptedException {
    System.out.println("main start:"+getCurrentTime());
    startTimer();
    Thread.sleep(1000*5); // dormancy 5 seconds 
    System.out.println("main  end:"+getCurrentTime());
  }

  public static void startTimer(){
    TimerTask task = new TimerTask() {
      @Override
      public void run() {
        System.out.println("task  run:"+getCurrentTime());
      }
    };
    Timer timer = new Timer();
    timer.schedule(task, 0);
  }
}

To make it easier to view the information by printing, we added some print information to the main method and called Thread.sleep to put the main thread to sleep for 1. In addition, an getCurrentTime method to get the current date has been added to the class.

The code above, in the startTimer method, first creates an TimerTask object (the task to be executed by the timer), then creates an Timer object, and then calls the schedule method of the Timer class. The Timer class has several schedule methods with different parameters. Here's what's used:


public void schedule(TimerTask task, long delay)

The implication of this method is that the timer will execute the task task after a delay of delay (milliseconds) time. If delay is negative or 0, the task is performed immediately. It is also a one-time task that will not be repeated later (or periodically).

For the Timer class, a method with the same functionality is also provided, as follows:


public void schedule(TimerTask task, Date time)

The difference between this method and the above method is that while the above method specifies a delay of 1 period of execution, this method specifies a specific point in time for execution. Note that if the current time of the system has exceeded the time specified by parameter time, the task will be executed immediately.

When we ran the above code, we found that the program immediately printed two messages similar to the following:

main start:2016-01-13 22:23:18
task run:2016-01-13 22:23:18

Since the delay parameter we passed to the schedule method here is 0, the task will be executed immediately, so the two statements will print out at the same time, as they should. You can change the value of delay to see what happens to the output. After about 5 seconds (that is, sleep time), another message was printed:

main end:2016-01-13 22:23:23

The time of printing the message is 5 seconds different from the above statement, which is in accordance with the 1 set by sleep, which is also reasonable.

However, we will find a very interesting phenomenon, we will find that the process will not exit, when the main main thread has finished, which means that the background thread created in the timer will not exit immediately even if there is no task to be executed later. Looking at the relevant java doc documentation, it is explained that the timer thread does not actively exit and needs to wait for garbage collection, but the pending garbage collection of java is not controlled by the code itself, but by the virtual machine.

The next study found that when creating Timer objects, and performing Timer timer = new Timer(); Statement, the timer thread is created. That is, even if the code above does not have timer.schedule (task, 0); This statement, the program will not exit. That doesn't make sense. I studied the source code of Timer class again and found that it also has a constructor with Boolean parameters:


public Timer(boolean isDaemon)

As you can see from the parameter name, if the parameter value is true, then the timer thread created by Timer is the daemon thread. Daemon thread means that when all worker threads in the java process exit, the daemon thread exits automatically.

In this case, we simply change the code that created the Timer object in the example above to Timer timer = new Timer(true);

After running the program, the program will exit when the main thread (main thread is not a daemon thread, but a worker thread) finishes. In other words, the timer thread also exits. After adding the parameter true, it is created as a daemon thread.

The problem is that in a real application scenario, there are a lot of worker threads running and the program doesn't just exit. What if you want the timer to quit or turn off immediately? We'll talk about that.

3. Exit the timer

The Timer class provides an cancel method to deactivate the timer. Calling the cancel method terminates the timer, discarding all currently scheduled tasks. This does not interfere with the task currently being performed, if any. Once a timer is terminated, its thread of execution terminates and no more tasks can be scheduled based on it.

Note that by calling this method within the run method of the timer task invoked by this timer, you can be absolutely sure that the task being executed is the last task executed by this timer. You can call this method repeatedly; But the second and subsequent calls are invalid.

Let's look at another example code:


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

public class TimerDemo {
  public static String getCurrentTime() {
    Date date = new Date();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    return sdf.format(date);
  }

  public static void main(String[] args) throws InterruptedException {
    System.out.println("main start:"+getCurrentTime());
    Timer timer = startTimer();
    Thread.sleep(1000*5); // dormancy 5 seconds 
    System.out.println("main  end:"+getCurrentTime());
    timer.cancel();
  }

  public static Timer startTimer(){
    TimerTask task = new TimerTask() {
      @Override
      public void run() {
        System.out.println("task  run:"+getCurrentTime());
      }
    };
    Timer timer = new Timer();
    timer.schedule(task, 0);
    return timer;
  }
}

Run the program exactly the same as the output of the previous example. The difference is, when the main method is over. The process exits, which means the timer thread is closed.

Because we called the cancel method in the main method. Note that if you are not calling cancel method 1 in TimerTask's run method, you must make sure that the desired task has been started or completed, otherwise if the task has not been started. If cancel is called, none of the tasks will be executed. Like the code above,

For example, in the code above, if we call cancel not in main, but timer.schedule (task, 0) in startTimer; timer.cancel (); Statement, after running it will be found that the timer task will not be executed, because it has not been canceled before execution.

4. Execute tasks regularly

In the example above, we are talking about a one time task, which is when the timer is up. When the task is completed, it will not be repeated later. In practical application, there are many scenarios that need to execute the same task repeatedly. This is also divided into two situations, 1 is every 1 period of time to execute the task, 2 is a fixed day (or weekly, monthly, etc.) at a certain point (or a few) to execute the task.

Let's look at case 1, an example of performing the same task every 10 seconds. The code is as follows:


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

public class TimerDemo {
  public static String getCurrentTime() {
    Date date = new Date();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    return sdf.format(date);
  }

  public static void main(String[] args) throws InterruptedException {
    System.out.println("main start:"+getCurrentTime());
    startTimer();
  }

  public static void startTimer(){
    TimerTask task = new TimerTask() {
      @Override
      public void run() {
        System.out.println("task  run:"+getCurrentTime());
        try {
          Thread.sleep(1000*3);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    };
    Timer timer = new Timer();
    timer.schedule(task, 1000*5,1000*10);
  }
}

Execute the above program, output information is as follows (because the timer did not stop, repeated execution of the task, will continue to output, here only copy the previous 1 output)

main start:2016-01-14 08:41:14
task run:2016-01-14 08:41:19
task run:2016-01-14 08:41:29
task run:2016-01-14 08:41:39
task run:2016-01-14 08:41:49
task run:2016-01-14 08:42:00
task run:2016-01-14 08:42:10
task run:2016-01-14 08:42:20
task run:2016-01-14 08:42:30
task run:2016-01-14 08:42:40

In the code above, we called timer.schedule (task, 1000*5,1000*10); This means that the task is delayed for 5 seconds and then repeated every 10 seconds. We observe the print time in the output as expected. In addition, it can be seen that the interval is calculated from the starting time of the execution of the task, that is, it is not 10 seconds after the completion of the task.

The Timer class has two methods that do this, as follows:


public void schedule(TimerTask task, long delay, long period)

public void schedule(TimerTask task, Date firstTime, long period)

The code above USES the first method. The difference between the two methods is the time of the first execution. The first method is executed after a specified delay of 1 millisecond. The second method is executed at a specified point in time.

Consider the following scenario. What happens if a task takes longer to execute than the next wait? Let's look at it through the code:


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

public class TimerDemo {
  public static String getCurrentTime() {
    Date date = new Date();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    return sdf.format(date);
  }

  public static void main(String[] args) throws InterruptedException {
    System.out.println("main start:"+getCurrentTime());
    startTimer();
  }

  public static void startTimer(){
    TimerTask task = new TimerTask() {
      @Override
      public void run() {
        System.out.println("task begin:"+getCurrentTime());
        try {
          Thread.sleep(1000*10);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        System.out.println("task  end:"+getCurrentTime());
      }
    };
    Timer timer = new Timer();
    timer.schedule(task, 1000*5,1000*5);
  }
}

Compared with the previous code, we only changed the code in 2 places and modified the print. 1 is to change sleep in run method to 10 seconds, and 2 is to change the execution cycle of the task to 5 seconds. In other words, the execution time of the task exceeds the interval between repeated execution of the task. Run the program, the previous output is as follows:

main start:2016-01-14 09:03:51
task begin:2016-01-14 09:03:56
task end:2016-01-14 09:04:06
task begin:2016-01-14 09:04:06
task end:2016-01-14 09:04:16
task begin:2016-01-14 09:04:16
task end:2016-01-14 09:04:26
task begin:2016-01-14 09:04:26
task end:2016-01-14 09:04:36
task begin:2016-01-14 09:04:36
task end:2016-01-14 09:04:46
task begin:2016-01-14 09:04:46
task end:2016-01-14 09:04:56

As you can see, after each task is completed, the next task is immediately executed. Because the time between the start of the task and its completion exceeds the interval between task repeats, it is repeated.

5. Execute tasks regularly (repeat execution at fixed time points)

Let's implement such a function, and execute a task at a fixed time at 1 am every day. This function is available in many systems, such as completing data backup, data statistics and other time-consuming and resource-consuming tasks in this task. The code is as follows:


import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class TimerDemo {
  public static String getCurrentTime() {
    Date date = new Date();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    return sdf.format(date);
  }

  public static void main(String[] args) throws InterruptedException {
    System.out.println("main start:" + getCurrentTime());
    startTimer();
  }

  public static void startTimer() {
    TimerTask task = new TimerTask() {
      @Override
      public void run() {
        System.out.println("task begin:" + getCurrentTime());
        try {
          Thread.sleep(1000 * 20);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        System.out.println("task  end:" + getCurrentTime());
      }
    };
    Timer timer = new Timer();
    timer.schedule(task, buildTime(), 1000 * 60 * 60 * 24);
  }

  private static Date buildTime() {
    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.HOUR_OF_DAY, 1);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);
    Date time = calendar.getTime();
    if (time.before(new Date())) {
      // If the current time is already early morning 1 After the dot, we have to add back 1 Day, otherwise the mission would be executed immediately. 
      // Many systems require immediate execution when the system is started 1 It's a second mission, but the next one is in the wee hours of the morning 1 So if I hit execute, what do I do? 
      // Quite simply, it is executed separately during system initialization 1 Secondary task (no timer needed, just the code to execute that task) 
      time = addDay(time, 1);
    }
    return time;
  }

  private static Date addDay(Date date, int days) {
    Calendar startDT = Calendar.getInstance();
    startDT.setTime(date);
    startDT.add(Calendar.DAY_OF_MONTH, days);
    return startDT.getTime();
  }

}

Because it is executed 24 hours apart, it is not possible to wait for the observed output.

6. Summary

This article describes the mechanism for performing timed tasks using the java Timer class. As you can see, there are a number of ways to be careful. For the example presented in this article, each timer corresponds to only one task.

This article will cover most of the application scenarios, but there are still some questions, such as how to include multiple tasks for a timer? Can you add tasks again after the timer is cancelled? What other methods are available in the Timer class? These questions will be covered in a later post.

The original link: http: / / www cnblogs. 51 kata/p com / / 5128745. html


Related articles: