Timer 的定义
有且仅有一个后台线程对多个业务进行定时定频的调度。Timer 类可以保证多个线程可以共享单个 Timer 对象而无需进行外部同步,所以 Timer 类是线程安全的。
核心的两个类
java.util.Timer
和 java.util.TimerTask
java.util.Timer。实际上是个线程,定时调度所拥有的 TimerTasks
.
一个 TimerTask
实际上就是一个拥有 run() 方法的类,需要定时执行的代码放到run方法体内,TimerTask
一般是以匿名类的方式创建。TimerTask
类是一个定时任务类,该类实现了 Runnable 接口,而且是一个抽象类
说明
java.util.TimerTask
TimerTask 类是一个抽象类,由 Timer 安排为一次执行或重复执行的任务。
/* TimerTask 的类定义,为抽象类,并且实现了 Runnable
可以通过继承该类,来实现自己的定时任务。*/
public abstract class TimerTask implements Runnable
它有一个抽象方法 run() 方法,该方法用于执行相应计时器任务要执行的操作。因此每一个具体的任务类都必须继承 TimerTask,然后重写 run() 方法。
另外它还有两个非抽象的方法:
- boolean cancel():取消此计时器任务。
- long scheduledExecutionTime():返回此任务最近实际执行的安排执行时间。
java.util.Timer
注意:javax.swing 包中也有一个Timer类,如果import中用到swing包, 要注意名字的冲突。
Timer 定时器实例有多种构造方法:
- Timer() : 创建一个新计时器。
- Timer(boolean isDaemon) :创建一个新计时器,可以指定其相关的线程作为守护程序运行。
- Timer(String name) :创建一个新计时器,其相关的线程具有指定的名称。
- Timer(String name, boolean isDaemon):创建一个新计时器,其相关的线程具有指定的名称,并且可以指定作为守护程序运行。
Timer 定时器的schedule() (调度方法)
下面例子部分参数说明:
delay: 延迟执行的毫秒数,即在delay毫秒之后第一次执行
period:重复执行的时间间隔
/* time为Date类型:在指定时间执行一次。 */
timer.schedule(task, time);
/* firstTime为Date类型,period为long
从firstTime时刻开始,每隔period毫秒执行一次。 */
timer.schedule(task, firstTime, period);
/* delay 为 long类型:从现在起过delay毫秒执行一次 */
timer.schedule(task, delay)
/* delay 为 long, period 为 long:从现在起过delay毫秒以后,每隔 period 毫秒执行一次。*/
timer.schedule(task, delay, period)
方法名称 schedule() 和 scheduleAtFixedRate() 的区别
- schedule() 方法更注重保持间隔时间的稳定:保障每隔period时间可调用一次
- scheduleAtFixedRate() 方法更注重保持执行频率的稳定:保障多次调用的频率趋近于period时间,如果任务执行时间大于period,会在任务执行之后马上执行下一次任务
scheduleAtFixedRate()
- scheduleAtFixedRate(TimerTask task, Date firstTime, long period):安排指定的任务在指定的时间开始进行重复的固定速率执行。
- scheduleAtFixedRate(TimerTask task, long delay, long period):安排指定的任务在指定的延迟后开始进行重复的固定速率执行。
实例代码说明
MyTimerTask.java
作为一个需要调度的任务类。
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimerTask;
public class MyTimerTask extends TimerTask {
private String name;
public MyTimerTask(String inputName) {
name = inputName;
}
@Override
public void run() {
Calendar calendar = Calendar.getInstance();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("current exec time is:"+ sf.format(calendar.getTime()));
// 重写来自于 TimerTask 的 run()
System.out.println("Current exec name is:" + name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
MyTimer.java
测试调度 MyTimerTask
import java.util.Timer;
public class MyTimer {
public static void main(String[] args) {
// 创建一个 timer 实例
Timer timer = new Timer();
// 创建一个 MyTimerTask 实例
MyTimerTask myTimerTask = new MyTimerTask("No.1");
/* 通过 timer 定时定频调用 myTimerTask的业务逻辑
* 即第一次执行是在当前时间的两秒之后,之后每隔一秒执行一次
*/
timer.schedule(myTimerTask, 2000L, 1000L);
}
}
输出结果
current exec time is:2018-06-05 14:35:22
Current exec name is:No.1
current exec time is:2018-06-05 14:35:23
Current exec name is:No.1
current exec time is:2018-06-05 14:35:24
Current exec name is:No.1
schedule() 的用法
代码紧跟着上面的例子来做。
在时间等于或者超过 time 的时候执行,且执行一次
/* 获取当前时间,并设置成距离当前时间3秒之后的时间
* 比如当前时间为: 2018-06-05 23:59:58
* 则设置之后的时间为: 2018-06-06 00:00:00
*/
Calendar calendar = Calendar.getInstance();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("current exec time is:"+ sf.format(calendar.getTime()));
calendar.add(Calendar.SECOND, 3);
/* 在时间等于或者超过 time 的时候执行,且执行一次 */
myTimerTask.setName("schedule1");
timer.schedule(myTimerTask, calendar.getTime());
输出的结果为:
current exec time is:2018-06-05 15:46:16
current exec time is:2018-06-05 15:46:19
Current exec name is:schedule1
时间等于或超过 time 的时候首次执行,之后每隔 period 毫秒重复执行一次 task
/* 获取当前时间,并设置成距离当前时间3秒之后的时间
* 比如当前时间为: 2018-06-05 23:59:58
* 则设置之后的时间为: 2018-06-06 00:00:00
*/
Calendar calendar = Calendar.getInstance();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("current exec time is:"+ sf.format(calendar.getTime()));
calendar.add(Calendar.SECOND, 3);
/**
* 时间等于或超过 time 的时候首次执行,之后每隔 period 毫秒重复执行一次 task
*/
myTimerTask.setName("schedule2");
timer.schedule(myTimerTask, calendar.getTime(), 3000L);
输出的结果为:
current exec time is:2018-06-05 15:54:32
current exec time is:2018-06-05 15:54:35
Current exec name is:schedule2
current exec time is:2018-06-05 15:54:38
Current exec name is:schedule2
current exec time is:2018-06-05 15:54:41
Current exec name is:schedule2
等待 delay 毫秒之后执行且执行一次 task
/**
* 等待 delay 毫秒之后执行且执行一次 task
*/
myTimerTask.setName("schedule3");
timer.schedule(myTimerTask, 1000);
输出结果为:
current exec time is:2018-06-05 16:00:06
current exec time is:2018-06-05 16:00:07
Current exec name is:schedule3
等待 delay 毫秒之后,首次执行,并且之后每隔 period 毫秒重复执行一次 task
/**
* 等待 delay 毫秒之后,首次执行,并且之后每隔 period 毫秒重复执行一次 task
*/
myTimerTask.setName("schedule4");
timer.schedule(myTimerTask, 1000, 3000);
输出结果为:
current exec time is:2018-06-05 16:01:36
current exec time is:2018-06-05 16:01:37
Current exec name is:schedule4
current exec time is:2018-06-05 16:01:40
Current exec name is:schedule4
current exec time is:2018-06-05 16:01:43
Current exec name is:schedule4
scheduleAtFixedRate() 的用法
时间等于或者超过 time 时首次执行 task,之后每隔 period 毫秒重复执行一次
/* 获取当前时间,并设置成距离当前时间3秒之后的时间
* 比如当前时间为: 2018-06-05 23:59:58
* 则设置之后的时间为: 2018-06-06 00:00:00
*/
Calendar calendar = Calendar.getInstance();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("current exec time is:"+ sf.format(calendar.getTime()));
calendar.add(Calendar.SECOND, 3);
/* 时间等于或者超过 time 时首次执行 task,之后每隔 period 毫秒重复执行一次 */
myTimerTask.setName("scheduleAtFixedRate1");
timer.scheduleAtFixedRate(myTimerTask, calendar.getTime(), 3000);
输出的结果为:
current exec time is:2018-06-05 16:11:48
current exec time is:2018-06-05 16:11:51
Current exec name is:scheduleAtFixedRate1
current exec time is:2018-06-05 16:11:54
Current exec name is:scheduleAtFixedRate1
current exec time is:2018-06-05 16:11:57
Current exec name is:scheduleAtFixedRate1
等待 delay 毫秒之后,首次执行,并且之后每隔 period 毫秒重复执行一次 task
/* 等待 delay 毫秒之后,首次执行,并且之后每隔 period 毫秒重复执行一次 task */
myTimerTask.setName("scheduleAtFixedRate2");
timer.scheduleAtFixedRate(myTimerTask, 1000, 3000);
输出的结果为:
current exec time is:2018-06-05 16:15:47
current exec time is:2018-06-05 16:15:48
Current exec name is:scheduleAtFixedRate2
current exec time is:2018-06-05 16:15:51
Current exec name is:scheduleAtFixedRate2
current exec time is:2018-06-05 16:15:54
Current exec name is:scheduleAtFixedRate2
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。