1. Overview
Implementing the function of executing tasks regularly in Java, mainly using two classes, Timer and TimerTask classes. The Timer is used to execute specified tasks in a background thread according to the specified plan.
TimerTask is an abstract class, and its subclass represents a task that can be planned by Timer. The specific code to be executed is written in the run method that TimerTask needs to be implemented.
2. Let’s take a look at the simplest example
Let's explain 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(); 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); }}In order to facilitate the observation information by printing, we added some printing information to the main method and called Thread.sleep to make the main thread sleep. In addition, a getCurrentTime method is added to the class to get the current date.
In the above code, in the startTimer method, a TimerTask object (the task to be executed by the timer) is created, and a Timer object is created, and the schedule method of the Timer class is called. The Timer class has multiple schedule methods with different parameters. What is used here is:
public void schedule(TimerTask task, long delay)
The meaning of this method is to execute the task task after the timer will delay (milliseconds) time. If delay is negative or 0, the task will be performed immediately. And it is a one-time execution task, and the task will not be repeated (or scheduled) subsequently executed.
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 specifies that the execution is delayed for a period of time, and this method specifies that the execution is performed at a specific point in time. 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 found that the program immediately prints two pieces of information similar to the following:
main start:2016-01-13 22:23:18
task run:2016-01-13 22:23:18
Because the delay parameter value we pass to the schedule method here is 0, the task will be executed immediately, so the time for printing the two statements is the same, which is what it should be. You can change the incoming delay value by yourself to see the changes in the output information. After about 5 seconds (i.e. sleep time), I continued to print 1 message:
main end:2016-01-13 22:23:23
The time for printing information is 5 seconds short of the above statement, which is consistent with the sleep setting, which is also very reasonable.
But we will find a very interesting phenomenon, and we will find that the process will not exit. At this time, the main main thread has ended. This means that after the timer completes the task, even if there are no tasks waiting to be executed later, the background thread created in the timer will not exit immediately. I checked the relevant Java doc documentation and explained that the timer thread will not exit actively and needs to wait for garbage collection, but Java's garbage collection cannot be controlled by the code itself, but is controlled by the virtual machine.
After research, it was found that when creating a Timer object and executing the Timer timer = new Timer(); statement, the timer thread will be created. In other words, 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 you can see from the parameter name, if the parameter value is true, the timer thread created by Timer is the daemon thread. The meaning of a daemon thread is that when all worker threads in the java process exit, the daemon thread will automatically exit.
At this time, we just need to change the code for creating the Timer object in the above example to: Timer timer = new Timer(true);
After you find that the program is run, the program will exit after the main thread (the main thread is not a daemon thread, but a worker thread) is completed, which means that the timer thread also exits, which means that after adding the parameter true, the created daemon thread is the daemon thread.
But the problem is that in real application scenarios, 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? We will introduce this below.
3. Exit of timer
The Timer class provides a cancel method to cancel the timer. Calling the cancel method will terminate this timer and discard all currently scheduled tasks. This does not interfere with the currently executing task (if it exists). Once the timer is terminated, its execution thread will also terminate and no more tasks can be scheduled according to it.
Note that by calling this method within the run method of the timer task called this timer, you can absolutely ensure 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 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); //Sleep for 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; }} Running the program is exactly the same as the output of the example above. The difference is that when the main method ends. The process will exit actively, which means that the timer thread has been closed.
Because we call the cancel method in the main method. Note that if you are not calling the cancel method in the run method of TimerTask, be sure to make sure that the task you want to execute has started or completed, otherwise if the task has not started to execute. Just call cancel, and all tasks will not be executed. For example, the above code,
For example, in the above code, if we do not call the cancel method in the main method, but add the timer.schedule(task, 0); statement in the startTimer method and add the timer.cancel(); statement after running, you will find that the timer task will not be executed, because it will be cancelled before execution is completed.
4. Execute tasks regularly
In the example above, we are introducing a one-time task, that is, the timer time has come. After the task is executed, it will not be repeated later. In actual applications, there are many scenarios that require the same task to be executed repeatedly regularly. There are two situations: one is to execute tasks every once in a while, and the other is to perform tasks at a certain (or several) time points every day (or weekly, monthly, etc.).
Let’s first look at the first case, which is an example of executing 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 and the output information is as follows (because the timer does not stop, and the task is repeated, the output will be continuously output. Only some of the previous outputs are copied here)
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 above code, we call timer.schedule(task, 1000*5,1000*10); This means that the task is delayed by 5 seconds, and then it will be repeated every 10 seconds. We observe that the printing time in the output information is the same as expected. In addition, it can be seen that the interval is calculated based on the task start time, that is, it is not to wait for another 10 seconds after the task is completed.
The Timer class has two methods to implement such functions, as follows:
public void schedule(TimerTask task, long delay, long period)public void schedule(TimerTask task, Date firstTime, long period)
The first method we use above code. The difference between the two methods is the time of the first execution. The first method is executed after a specified delay of a period of time (in milliseconds); the second method is executed at a specified time point.
At this time, we consider the following scenario. If the execution time of a task exceeds the next waiting time, what will happen? 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 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 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
It can be seen that after each task is executed, the next task will be executed immediately. Because the time taken from the start of the task to the completion of the task has exceeded the interval between the task repetition, the execution will be repeated.
5. Execute tasks regularly (repeat the fixed time point)
Let’s implement such a function, perform a task regularly at 1 a.m. every day, which has this function in many systems, such as completing time-consuming and resource-consuming tasks such as data backup and data statistics 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 after 1 a.m., 1 day is needed, otherwise the task will be executed immediately. //Many systems often need to execute tasks immediately when the system starts, but they need to execute them at 1 a.m. every day. What should I do? //It's very simple, just execute the task separately when the system initializes the call (no timer is needed, it's 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 at 24 hours apart, it is impossible to wait for the observation of the output.
6. Summary
This article introduces the mechanism of how to perform timed tasks using the Java Timer class. It can be seen that there are still many ways to pay attention to. In the examples introduced in this article, each timer only corresponds to one task.
The content introduced in this article can meet most application scenarios, but there are still some problems, such as including multiple tasks for a timer? Can I add tasks again after the timer is cancelled? What other methods are available in the Timer class? These questions will be introduced in the following blog post.
Original link: http://www.cnblogs.com/51kata/p/5128745.html
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.