定时 / 计划功能
定时 / 计划功能在移动开发领域使用较多,比如 Android 技术。定时计划任务功能在 Java 中主要使用的就是 Timer 对象,它在内部使用多线程的方式进行处理,所以它和线程技术还是有非常大的关联的。
定时器 Timer 的使用
在 JDK 库中 Timer 类主要负责计划任务的功能,也就是在指定的时间开始执行某一个任务。Timer 类的方法列表如下所示:
构造方法
常用方法
Timer 类的主要作用就是设置计划任务,但封装任务的类却是 TimerTask 类,类结构如下:
方法如下:
执行计划任务的代码要放入 TimerTask 的子类中,因为 TimerTask 是一个抽象类。
方法 schedule(TimerTask task, Date time) 的测试
该方法的作用是在指定日期执行一次某一任务。
1.计划时间晚于当前时间:在未来执行的效果
Run1.java
运行结果
运行完了,但进程还未销毁,这是为什么呢?
分析
Timer 的无参构造方法会启动一个新线程,这个新启动的线程不是守护线程,它一直在运行。
修改 Timer 的构造方法,传入参数 true,表示设置该线程为守护线程
运行结果
可以看到主线程运行完毕,守护线程中的任务未执行线程就结束了。
2.计划时间早于当前时间:提前运行的效果
如果执行任务的时间早于当前时间,则立即执行 task 任务。
示例代码
运行结果
3.多个 TimerTask 任务及延时的测试
Timer 中允许有多个 TimerTask 任务
Run2.java
运行结果
Timer 是以队列的形式排队执行的,所以执行的时间可能和预期的时间不一致,因为前面的任务可能消耗时间较长,则后面的任务运行的时间也会被延迟。
Run2Later.java
运行结果
分析
由于 task1 需要用时 20 秒执行完任务,task1 开始的时间是 11:33:00,那么将要影响 task2 的计划任务执行的时间,task2 以此时间为基准,向后延迟 20 秒,task2 在 11:33:20执行任务。因为 Task 是被放入队列中的,得一个一个顺序运行。
方法 schedule(TimerTask task, Date firsttime, long period) 的测试
该方法的作用是在指定日期之后,按指定的间隔周期性地无限循环执行某一任务。
1.计划时间晚于当前时间:在未来执行的效果
Run.java
运行结果
从运行结果来看,每隔 4 秒运行一次 TimerTask 任务,并且是无限期地重复执行。
2.计划时间早于当前时间:提前运行的效果
如果执行任务的时间早于当前时间,则立即执行 task 任务。
示例代码
运行结果
3.任务执行时间被延迟
Run2_1.java
运行结果
任务被延迟但还是一个一个顺序运行。
4.TimerTask 类的 cancel() 方法
TimerTask 类中的 cancel() 方法是将自身从任务队列中清除,其他任务不受影响。
Run2.java
运行结果
TimerTaskA仅运行一次后被清除了。
5.Timer 类的 cancel() 方法
和 TimerTask 类中的 cancel() 方法清除自身不同,Timer 类中的 cancel() 方法的作用是将任务队列中的全部任务清空。
Run3.java
运行结果
TimerTaskA运行一次后所有任务都被移除。
6.Timer 的 cancel() 方法注意事项
Timer 中的 cancel() 方法有时并不一定会停止执行计划任务,而是正常执行。
Run4.java
运行结果
分析
任务并没有停止执行,这是因为Timer 中的 cancel() 方法有时并没有争抢到 queue 锁,所以 TimerTask 中的任务继续正常执行。
方法 schedule(TimerTask task, long delay) 的测试
该方法的作用是以执行 schedule(TimerTask task, long delay) 方法当前的时间为基准,在此基础上延迟指定的毫秒数后执行一次 TimerTask 任务。
Run.java
运行结果
任务 task 被延迟了 7 秒执行。
方法 schedule(TimerTask task, long delay, long period) 的测试
该方法的作用是以执行 schedule(TimerTask task, long delay, long period) 方法当前的时间为基准,在此基础上延迟指定的毫秒数,再以某一间隔时间无限次数地执行某一任务。
Run.java
运行结果
凡是使用方法中带有 period 参数的,都是无限循环执行 TimerTask 中的任务。
方法 scheduleAtFixedRate(TimerTask timer, Date firstTime, long period)
1.测试 schedule 方法不延时
Run1.java
运行结果
如果执行任务的时间没有被延迟,则下一次执行时间是上一次任务的开始时间加上 delay 时间。
2.测试 schedule 方法延时
Run2.java
运行结果
如果执行任务的时间被延迟,那么下一次任务的执行时间以上一次任务“结束”的时间为参考来计算。
3.测试 scheduleAtFixedRate 方法不延时
Run3.java
运行结果
如果执行任务的时间没有被延迟,则下一次执行时间是上一次任务的开始时间加上 delay 时间。
4.测试 scheduleAtFixedRate 方法延时
Run4.java
运行结果
如果执行任务的时间被延迟,那么下一次任务的执行时间以上一次任务“结束”的时间为参考来计算。
5.验证 schedule 方法不具有追赶执行性
Run5.java
运行结果
时间 “2014-10-12 15:37:00” 到 “2014-10-12 15:43:53” 之间的时间所对应的 Task 任务被取消了,不执行了。这就是 Task 任务不追赶的情况。
6.验证 scheduleAtFixedRate 方法具有追赶执行性
Run6.java
运行结果
scheduleAtFixedRate方法可以快速连续地出现两次或更多的执行,从而使后续执行能够“追赶上来”。两个时间段内所对应的 Task 任务被 “补充性” 执行了,这就是 Task 任务追赶执行的特性。
网友评论