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

Java: Use the java Timer class to realize the function of timing execution tasks

1. Overview

To realize the function of timing execution tasks in java, two classes are mainly used, Timer and TimerTask. The Timer is used to execute the specified task according to the specified schedule in a background thread.
TimerTask is an abstract class whose subclasses represent a task that can be scheduled by Timer. The specific code to be executed is written in the run method that TimerTask needs to implement.

2. Let's look at the simplest example first.

Let through code.

Copy 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); //Sleep for 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
facilitate the observation of information by printing, we add some printing information to the main method, and call Thread.sleep to let the main thread sleep.
In addition, a getCurrentTime method for obtaining the current date is added to the class.

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

  public void schedule(TimerTask task, long delay)

  The meaning of this method is that the timer will delay the delay (milliseconds) time before executing the task task. If delay is negative or 0, the task will be performed immediately. And it is a one-time execution task, and the subsequent execution of the task will not be repeated (or scheduled).

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

  public void schedule(TimerTask task, Date time)

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

When running the above code, we find that the program immediately prints 2 pieces of information similar to the following:
main start: 2016-01-13 22:23:18
task run: 2016-01-13 22:23:18

because we give the schedule method here The passed delay parameter value is 0, so the task will be executed immediately, so the two statements print out the same time, which is as it should be. You can change the incoming delay value yourself to see the change in the output information. After about 5 seconds (that is, the time of sleep), 1 message continues to be printed:

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

The time of printing information is 5 seconds different from the above statement, which is consistent with the sleep setting, which is also very reasonable.

But we will find a very interesting phenomenon. We will find that the process will not exit. At this time, the main thread of main has ended. This means that after the timer completes the task, even if there are no tasks waiting to be executed, the timer will create The background thread also doesn't exit immediately. Looking at the relevant java doc documents, it explains that the timer thread will not actively exit and needs to wait for garbage collection, but the garbage collection of java cannot be controlled by the code itself, but by the virtual machine.

After researching, it is found that when the Timer object is created and the Timer timer = new Timer(); statement is executed, the timer thread will be created. That is to say, even if the above code does not have the timer.schedule(task, 0); statement, the program will not exit. I feel this is quite unreasonable. I studied the source code of the Timer class again, and found that it also has a constructor with boolean parameters:

public Timer(boolean isDaemon)

As can be seen from the parameter name, if the parameter value is true, the timer thread created by Timer for the daemon thread. The meaning of the daemon thread is that when all the worker threads in the java process exit, the daemon thread automatically exits.

At this time, we only need to change the code for creating the Timer object in the above example to: Timer timer = new Timer(true);

After finding the running program, after the main thread (the main thread is not a daemon thread, but a worker thread) ends, the program will Exit, that is to say, the timer thread also exits, indicating that after adding the parameter true, it is created as a daemon thread.

   But the problem is that in a real application scenario, there are many worker threads running, and the program will not exit casually. So what if you want the timer to exit or close immediately? This we introduce below.

3. Exit of the timer

  The Timer class provides a cancel method to cancel the timer. Calling the cancel method terminates this timer, discarding all currently scheduled tasks. This does not interfere with the currently executing task (if it exists). Once the timer is terminated, its execution thread also terminates and no more tasks can be scheduled based on it.
  Note that calling this method inside the run method of the timer task invoked by this timer provides absolute assurance that the task being executed is the last task executed by this timer. This method can be called repeatedly; however, the second and subsequent calls have no effect.

    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); //休眠5秒
        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, and the output is exactly the same as in the previous example. The difference is when the main method ends. The process will actively exit, which means that the timer thread has been closed.
Because we called the cancel method in the main method. Note that if the cancel method is not called in the run method of the TimerTask, you must pay attention to ensure that the task you want to execute has already started or completed, otherwise if the task has not yet begun to execute. If cancel is called, all tasks will not be executed. For example, the above code,

such as the above code, if we do not call the cancel method in the main method, but add the timer.cancel(); statement after the timer.schedule(task, 0); statement in the startTimer method, it will run It is found that the timer task will not be executed, because it is cancelled and aborted before it can be executed.

Fourth, timed execution of tasks In

    the above example, we introduce a one-time task, that is, when the timer expires, and the task is executed, it will not be repeated later. In practical applications, there are many scenarios where the same task needs to be executed regularly and repeatedly. This is also divided into two situations, one is to perform tasks at regular intervals, and the other is to perform tasks at a certain (or several) time points every day (or every week, every month, etc.).

    Let's first look at the first case, an example of implementing 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);
    }
}
Copy code
Execute the above program and output information As follows (because the timer does not stop and the task is repeatedly executed, it will continue to output, only some of the previous outputs are copied here)

copy code
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:40Copy
code
In the above code, we call timer.schedule(task, 1000*5,1000*10); This means that the task is executed after a delay of 5 seconds, Then it will repeat every 10 seconds. We observe the time printed in the output, which is as expected. In addition, it can be seen that the interval is calculated from the start time of the task execution, that is, it does not wait for 10 seconds after the task execution is completed.

The Timer class has two methods to implement this function, as follows:
public void schedule(TimerTask task, long delay, long period)

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

Our 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 period (in milliseconds); the second method is executed at the specified time point.

At this time, we consider the following scenarios. If the execution time of a task exceeds the next waiting time, what will happen? Let's look at 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);
    }
}
Copy code
Compared with the previous code, we only changed 2 codes and modified the print, one is to change the sleep in the run method to 10 seconds, and the other is to change the execution cycle of the task Change to 5 seconds. That is to say, 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:56Copy
code
It can be seen that each task Once the execution is complete, the next task is executed immediately. Because the time-consuming from the start of the task to the completion of the task has exceeded the interval of task repetition, it will be repeated.

5. Scheduled task execution (repeated execution at a fixed time point)

Let’s implement such a function, execute a task regularly at 1:00 a.m. every day, which has this function in many systems, such as completing data backup and data in this task. Time-consuming and resource-intensive tasks such as statistics.

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 after 1:00 am, you need to add 1 day later, otherwise the task will be executed immediately.
            //Many systems often need to execute a task immediately when the system starts, but then it needs to be executed at 1 am every day. What should I do?
            //It's very simple, just execute the task once when the system is initialized (no need to use a timer, just execute the code of 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();
    }

}


url:http://www. cnblogs.com/51kata/p/5128745.html

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326395883&siteId=291194637