版权声明:如果觉得我的博客对你有帮助, 请点赞或评论! https://blog.csdn.net/zongf0504/article/details/88925009
Timer 是jdk 自身提供的定时器, 可使用于实现一些简单的定时任务,如在某一时刻执行一次任务或以固定时间间隔执行任务. 一个Timer 实例可调度多个TimerTask, 底层使用队列(TaskQueue)存储, 不能并发启动定时任务. 因此, 对于复杂的定时任务, 笔者推荐使用quartz.
1. Timer 常用API
默认情况下,Timer 创建的线程为用户线程, 如果想让其为守护进程的话, 创建时需要设置isDaemon 为true.
方法签名 | 方法描述 |
---|---|
public Timer(String name) | 构造方法, 创建定时器, 并指定线程名称. 以定时调度线程为用户线程 |
public Timer(boolean isDaemon) | 构造方法, 创建定时器, isDaemon 设置为trues时表示以守护线程执行 |
public Timer(String name, boolean isDaemon) | |
public void schedule(TimerTask task, long delay) | 只调度一次, 延迟delay毫秒之后执行 |
public void schedule(TimerTask task, Date time) | 只调度一次, 在具体时刻time 执行 |
public void schedule(TimerTask task, long delay, long period) | 循环调度, 在delay毫秒之后开始,每隔period毫秒执行一次 |
public void schedule(TimerTask task, Date firstTime, long period) | 循环调度, 在时刻firstTime开始调度, 每隔period毫秒执行一次 |
public void scheduleAtFixedRate(TimerTask task, long delay, long period) | 和schedule方法类似, 只是错过的任务会被继续执行 |
public void scheduleAtFixedRate(TimerTask task, Date firstTime, long period) | 和schedule方法类似, 只是错过的任务会被继续执行 |
public int purge() | 清理所有已取消状态的TimerTask |
public void cancel() | 取消所有调度 |
2. 调度测试
2.1 延时调度一次
程序启动3秒之后, 执行一次
public static void main(String[] args) throws InterruptedException {
// 创建定时器
Timer timer = new Timer("myTimer");
// 创建定时任务
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
System.out.println(LocalDateTime.now() + "-hello");
}
};
// 添加调度
timer.schedule(timerTask ,3000);
}
2.2 定时调度一次
定时任务在下一分钟00秒时执行一次
public static void main(String[] args) throws InterruptedException {
// 创建定时器
Timer timer = new Timer("myTimer");
// 创建定时任务
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
System.out.println(LocalDateTime.now() + "-hello");
}
};
Date nextMinute = nextMinute();
System.out.println("now:" + new Date() + ", execute:" + nextMinute);
// 添加调度
timer.schedule(timerTask ,nextMinute);
}
// 获取下一分钟的时间
private static Date nextMinute(){
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MINUTE, 1);
calendar.add(Calendar.SECOND, -calendar.get(Calendar.SECOND));
return calendar.getTime();
}
2.3 循环调度n次
定时任务每隔1秒中执行一次, 执行n次后停止
public static void main(String[] args) throws InterruptedException {
// 创建定时器
Timer timer = new Timer("myTimer");
// 创建定时任务
TimerTask timerTask = new TimerTask() {
private int times = 0;
@Override
public void run() {
// 执行5次后, 取消任务
if(++times ==5 ){
this.cancel();
}
System.out.println(LocalDateTime.now() + "-hello, times:" + times);
}
};
// 添加调度
timer.schedule(timerTask ,0, 1000l);
}
2.4 无限循环调度
定时任务每隔1秒中执行一次, 无限循环
public static void main(String[] args) throws InterruptedException {
// 创建定时器
Timer timer = new Timer("myTimer");
// 创建定时任务
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
System.out.println(LocalDateTime.now() + "-hello");
}
};
// 添加调度
timer.schedule(timerTask ,0, 1000l);
}
3. scheduleAtFixedRate 与 schedule 区别
scheduleAtFixedRate和schedule 的唯一区别就是, schedule 会将错过执行的定时任务丢弃, 而scheduleAtFixedRate 则会补上。
3.1 测试用例
public static void main(String[] args) {
TimerTask timerTask = new TimerTask() {
private int times = 0;
@Override
public void run() {
try {
if(times++ ==3){
this.cancel();
}
System.out.printf("planExecTime:%s, now:%s, times:%s\n", new Date(scheduledExecutionTime()), new Date(), times);
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Timer timer = new Timer("myTimer");
timer.schedule(timerTask, nextMinute(), 1000);
}
private static Date nextMinute(){
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MINUTE, 1);
calendar.add(Calendar.SECOND, -calendar.get(Calendar.SECOND));
return calendar.getTime();
}
3.2 scheduleAtFixedRate 调度结果
从输出结果上来看, 定时任务计划执行时间与实际执行时间只有第一次一致,其它都不一致。 在定时任务执行的时间内,本应该执行的定时任务会依次被执行。
planExecTime:Sun Mar 31 18:03:00 CST 2019, now:Sun Mar 31 18:03:00 CST 2019, times:1
planExecTime:Sun Mar 31 18:03:01 CST 2019, now:Sun Mar 31 18:03:03 CST 2019, times:2
planExecTime:Sun Mar 31 18:03:02 CST 2019, now:Sun Mar 31 18:03:06 CST 2019, times:3
planExecTime:Sun Mar 31 18:03:03 CST 2019, now:Sun Mar 31 18:03:09 CST 2019, times:4
3.2 schedule 调度结果
从输出结果上可以看出, 计划执行时间和实际执行时间一致. 虽然笔者的调度时间为每隔1秒, 但是定时任务执行需要3秒的时间。 在定时任务执行期间,本应该有的调度全部丢弃。
planExecTime:Sun Mar 31 18:01:00 CST 2019, now:Sun Mar 31 18:01:00 CST 2019, times:1
planExecTime:Sun Mar 31 18:01:03 CST 2019, now:Sun Mar 31 18:01:03 CST 2019, times:2
planExecTime:Sun Mar 31 18:01:06 CST 2019, now:Sun Mar 31 18:01:06 CST 2019, times:3
planExecTime:Sun Mar 31 18:01:09 CST 2019, now:Sun Mar 31 18:01:09 CST 2019, times:4