首先来看看此类在JavaSE文档中对Timer类的8点解释:
1.线程的工具,用于在后台线程中安排将来执行的任务。可以将任务安排为一次性执行,或者以固定间隔重复执行。 |
---|
2.对应于每个Timer对象的是一个后台线程,用于按顺序执行所有计时器的任务。 |
3.计时器任务应该快速完成。 |
4.如果计时器任务花费过多时间来完成,它会“占用”计时器的任务执行线程。反过来,这可以延迟后续任务的执行,后续任务可以在紧急任务最终完成时(以及如果)快速连续地“聚集”并执行。 |
5.默认情况下,任务执行线程不作为守护程序线程运行,因此它能够阻止应用程序终止。如果调用者想要快速终止计时器的任务执行线程,则调用者应该调用计时器的cancel方法。 |
6.如果计时器的任务执行线程意外终止,例如,因为stop调用了它的方法IllegalStateException,那么在计时器上调度任务的任何进一步尝试都将导致 ,就像cancel 调用了计时器的方法一样。 |
7.此类是线程安全的:多个线程可以共享单个 Timer对象,而无需外部同步。 |
8.此类不提供实时保证:它使用该Object.wait(long)方法计划任务。 |
继承结构:

方法:
发现方法 schedule占Timer类的大部分,从schedule方法中可以看出执行计划任务的代码要放入TimerTask的子类中,因为TimerTask是一个抽象类。
下面我将对schedule进行了解:
此方法有如下几种执行情况:
- 未来执行
- 提前执行
- 延时执行
- 不延时执行
1.方法schedule(TimerTask task,Date time)
作用:该方法的作用是在指定的日期执行一次某一任务
未来执行:(执行的时间比当前的时间晚)
任务虽然运行结束,但进程没有被销毁。此问题需要我们来看看创建Timer对象的源码:
该构造方法调用的是如下有参构造方法:
由此可知,创建了一个Timer对象就是启动了一个新线程,此线程不是守护线程,它是一直运行的。正如文档对它的解释。
那么如何将它改为守护线程呢?
很简单,修改如下语句:
看看运行结果:
此时任务执行完毕,线程也被销毁了。
.
提前执行(计划的时间比当前时间要早)
作用:如果执行任务的时间早于当前时间,则立即执行task任务。
往main中添加如下语句:
执行结果:
延时执行(多个TimerTask任务)
Timer是允许有多个TimerTask任务的。
运行结果:
TimerTask是以队列的方式一个一个顺序执行的,所以执行的时间可能会和预期的不一致,为什么这么说呢,因为每个TimerTask的执行时间有长短,前面执行时间长会拖延后面的执行时间。
2.方法 schedule(TimerTask task, Date firstTime, long period)
作用:过了指定日期之后,按指定的间隔周期性地无限循环地执行某一任务。
未来执行(计划时间要比当前时间晚)
修改前面代码的两处地方:
运行结果:
每4秒无限期重复执行TimerTask任务。
提前运行(计划时间要比当前时间早)
如果计划时间早于当前时间,则立即执行task任务。
此时task任务立即执行了。
延时执行
修改MyTask类中run()方法:

执行效果:

3.方法schedule(TimerTask task, long delay)
作用:在指定的延迟后安排指定的毫秒数后任务执行。
延时执行
任务task的执行被延迟了4秒。
4.方法schedule(TimerTask task, long delay, long period)
作用:在指定的延迟之后开始,为重复的固定延迟执行安排指定的任务。
延时执行
修改上面代码:
运行效果:
效果为:无限循环执行TimerTask中的任务。
此测试效果证明凡是使用方法中带有period参数的,都是无限循环执行TimerTask中的任务的。
5.方法scheduleAtFixedRate(TimerTask task, Date firstTime, long period)
作用:从指定的时间开始,为重复的固定速率执行安排指定的任务。
下面对方法schedule与scheduleAtFixedRate进行对比:
1.都是按顺序执行的,不用考虑非线程安全的问题。
2.都是执行任务的时间被延时:
schedule: 下一次任务的执行时间参考上一次开始时的时间来计算。
scheduleAtFixedRate:下一次任务的执行时间参考上一次结束时的时间来计算。
使用schedule任务不延时执行
运行效果:
结果表明,在不延时的情况下,如果执行任务的时间没有延时,则下一次执行任务的时间是上一次任务的开始时间加上delay时间。
使用schedule任务延时执行
修改如下两处代码:
运行效果:
结果表明:在不延时的情况下,如果执行任务的时间被延时,则下一次执行任务的时间是上一次任务的结束时间为参考来计算。
使用scheduleAtFixedRate任务不延时执行
将上面的时间改回来,然后把schedule方法改为scheduleAtFixedRate:
运行效果:
结果表明,在不延时的情况下,如果执行任务的时间没有延时,则下一次执行任务的时间是上一次任务的开始时间加上delay时间。
下面的延迟任务情况就不做介绍了,和上面的操作一样,依次判断。
验证schedule方法不具有追赶执行性。
运行效果:
从结果可以看出: 时间:2019-3-24 15:39:00 当前时间:2019-3-24 17:30:59之间的时间所对应的Task任务被取消了,schedule方法不具有追赶执行性。
将schedule方法改为scheduleAtFixedRate方法。
运行效果:
运行效果说明:scheduleAtFixedRate方法具有追赶执行性。
下面简单介绍下TimerTask中的方法:
cancel():将自身任务从任务队列中清除,其他任务不被影响。
而Timer中的cancel()方法:终止此计时器,丢弃当前计划的任何任务,而且进程会被销毁掉。不过有时并不一定会停止执行计划任务,而是正常执行,这是因为Timer类中的cancel()方法有时并没有争抢到queue锁,所以TimerTask类中的任务继续正常执行。