1. Introduction
Timer (Timer) is a utility class for scheduling tasks (java.util.TimerTask) to be executed after a specified time or repeated at specified intervals. It can be used to perform operations such as timing tasks, timing scheduling, and time delays.
Timer (Timer) can be applied to many scenarios, such as:
Scheduling tasks (fixed rate) : When you need to perform tasks according to the scheduled time, you can use timers. For example, data backup is performed every morning, reports are generated regularly, notifications are sent regularly, etc. That is, the two overloaded methods of scheduleAtFixedRate.
Timeout handling (fixed delay) : When you need to handle the timeout of an operation, you can use a timer. For example, set the timeout period of an operation, and if it is not completed within the specified time, execute the corresponding timeout processing logic. That is, the four overloaded methods of schedule.
Timers in Java: java.util.Timer , its common methods:
Java 8 Chinese Edition - Online API Manual - Coding Tool
Modifier and Type |
Method and Description |
Parameter Description |
void |
cancel() Terminates this timer, discarding any currently scheduled tasks. |
/ |
int |
purge() Removes all canceled tasks from this timer's task queue. |
/ |
void |
schedule(TimerTask task, Date time) Schedule the specified task to execute at the specified time. If this time has passed, schedule the task to execute immediately |
task: the task to be scheduled time : time to execute the task |
void |
schedule(TimerTask task, Date firstTime, long period) Performs repeated fixed-delay executions of the specified task, starting at the specified time . |
task: the task to be scheduled firstTime: the time when the task was executed for the first time period: the time interval of the continuous task in milliseconds |
void |
schedule(TimerTask task, long delay) Schedules the specified task to execute after the specified delay. |
task: the task to be scheduled delay: The time to delay in milliseconds before executing the task |
void |
schedule(TimerTask task, long delay, long period) Starting after the specified delay , re-executes the specified task that was executed with a fixed delay . |
task: the task to be scheduled delay: The time to delay in milliseconds before executing the task period: the time interval of the continuous task in milliseconds |
void |
scheduleAtFixedRate(TimerTask task, Date firstTime, long period) Performs repeated, fixed-rate executions of the specified task, starting at the specified time . |
task: the task to be scheduled firstTime: the time when the task was executed for the first time period: the time interval of the continuous task in milliseconds |
void |
scheduleAtFixedRate(TimerTask task, long delay, long period) Begins after the specified delay , re-executing the specified task at a fixed rate . |
task: the task to be scheduled delay: The time to delay in milliseconds before executing the task period: the time interval of the continuous task in milliseconds |
2. The difference between schedule and scheduleAtFixedRate method
These two methods are task scheduling methods. The difference between them is that the schedule will ensure that the interval between tasks is strictly executed according to the defined period parameter. If a certain scheduling time is relatively long, then the subsequent time will be postponed to ensure the scheduling interval They are all period, and scheduleAtFixedRate is strictly in accordance with the scheduling time. If a certain scheduling time is too long, then the interval will be shortened to ensure that the next scheduling will be executed at the scheduled time. Take a chestnut: you schedule once every 3 seconds, then the normal time is 0,3,6,9s, if the second scheduling takes 2s, if it is a schedule, it will become 0,3+2 For times like ,8,11, the interval is guaranteed, and scheduleAtFixedRate will become 0,3+2,6,9, the interval is compressed, and the scheduling time is guaranteed.
3. Timer (Timer) using steps
To implement a timed task, we only need to implement the run method of TimerTask. Each task has the next execution time nextExecutionTime (milliseconds). If it is a periodic task, then each execution will update this time as the next execution time. When nextExecutionTime is less than the current time, it will be executed.
(1) The first step: create a Timer.
(2) The second step: create a TimerTask.
(3) The third step: use Timer to execute TimerTask.
The third step is undoubtedly what we are most concerned about at present, that is, timer.schedule(myTask, 2000L, 1000L). What he means is that myTask starts executing for the first time after two seconds, and then every second. This is just the most basic usage. It reflects the process of Timer timing execution.
Example 1 : Timeout handling (fixed delay)
Start executing after 2 seconds, only once
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimeTest {
public static void main(String[] args) {
System.out.println("当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss:SSS").format(new Date()));
Timer timer = new Timer(); // (1)第一步:创建一个Timer。
timer.schedule(new TimerTask() { // (2)第二步:创建一个TimerTask。(3)第三步:使用Timer执行TimerTask。
@Override
public void run() {
System.out.println("Timer is running");
System.out.println("当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss:SSS").format(new Date()));
}
}, 2000);
}
}
operation result:
Current time: 2023-08-19 22-45-46:161
Timer is running
Current time: 2023-08-19 22-45-48:169
Example 2 : Scheduling tasks (fixed rate)
To perform periodic tasks, you only need to add the third parameter period of the schedule.
Start executing after 2 seconds and execute every 1 second
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimeTest {
public static void main(String[] args) {
System.out.println("当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss:SSS").format(new Date()));
Timer timer = new Timer(); // (1)第一步:创建一个Timer。
timer.schedule(new TimerTask() { // (2)第二步:创建一个TimerTask。(3)第三步:使用Timer执行TimerTask。
@Override
public void run() {
System.out.println("Timer is running");
System.out.println("当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss:SSS").format(new Date()));
}
}, 2000, 1000);
}
}
operation result:
Current time: 2023-08-19 22-48-10:190
Timer is running
Current time: 2023-08-19 22-48-12:200
Timer is running
Current time: 2023-08-19 22-48-13:203
Timer is running
Current time: 2023-08-19 22-48-14:216
Example 3 : 2 Timer instances schedule tasks (fixed rate)
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimeTest {
public static void main(String[] args) {
System.out.println("timer当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss:SSS").format(new Date()));
Timer timer = new Timer(); // (1)第一步:创建一个Timer。
timer.schedule(new TimerTask() { // (2)第二步:创建一个TimerTask。(3)第三步:使用Timer执行TimerTask。
@Override
public void run() {
System.out.println("Timer is running");
System.out.println("timer当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss:SSS").format(new Date()));
}
}, 2000, 1000);
System.out.println("timer2当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss:SSS").format(new Date()));
Timer timer2 = new Timer(); // (1)第一步:创建一个Timer。
timer2.schedule(new TimerTask() { // (2)第二步:创建一个TimerTask。(3)第三步:使用Timer执行TimerTask。
@Override
public void run() {
System.out.println("Timer2 is running");
System.out.println("timer2当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss:SSS").format(new Date()));
}
}, 3000, 2000);
}
}
operation result:
timer current time: 2023-08-20 00-08-06:746
Timer2 current time: 2023-08-20 00-08-06:748
Timer is running
timer current time: 2023-08-20 00-08-08:750
Timer is running
Timer2 is running
Timer2 current time: 2023-08-20 00-08-09:755
timer current time: 2023-08-20 00-08-09:755
Timer is running
timer current time: 2023-08-20 00-08-10:769
Timer2 is running
Timer2 current time: 2023-08-20 00-08-11:768
Timer is running
timer current time: 2023-08-20 00-08-11:784
Timer is running
timer current time: 2023-08-20 00-08-12:787
Timer2 is running
Timer2 current time: 2023-08-20 00-08-13:770
4. Defects of Timer
1. Since there is only one thread for executing tasks, if the execution time of a certain task is too long, the timing accuracy of other tasks will be destroyed. For example, if one task is executed every 1 second, and another task takes 5 seconds to execute, then if it is a fixed-rate task, it will be executed 5 times after the task is completed in 5 seconds, and the fixed-delay task will lose 4 executions.
2. If an exception is thrown during the execution of a certain task, the execution thread will terminate, causing other tasks in the Timer to no longer be executed.
3. Timer uses absolute time, that is, a certain point in time, so its execution depends on the system time. If the system time is modified, the task may not be executed.
5. A Better Alternative
Due to the defects mentioned above in Timer, in JDK1.5, we can use ScheduledThreadPoolExecutor to replace it, use Executors.newScheduledThreadPool factory method or use the constructor of ScheduledThreadPoolExecutor to create timed tasks, which are based on the implementation of thread pool and will not There are the above problems with Timer, when the number of threads is 1, it is equivalent to Timer.