通过以上测试对比,我们可以感受到Timer中固定速率和固定延时的区别,但为了避免出错,使用Timer时应让TimerTask耗时尽可能短 。
4. 其他要点
- 以上是仅第3次任务加上了耗时11秒,如果是所有任务都耗时11秒呢?
- 如果改为schedule(TimerTask task, Date firstTime, long period)和scheduleAtFixedRate(TimerTask task, Date firstTime, long period)来调度任务,firstTime指定为10点 , 而当前系统时间为11点,会出现什么情况呢?
- 如果TimerTask执行过程中抛出了异常会发生什么事情?
四、调度多个TimerTask在上一节中,介绍的是一个可重复执行的TimeTask,如果执行耗时大于设定的间隔period , 将会影响该TimerTask下一次执行的时间点 。
而这一节则是为了单独说明,一个Timer同时调度多个TimeTask也会互相影响 。
示例:
TimerTask task1 = new TimerTask() {private int i = 1;@Overridepublic void run() {System.out.print(i + " task1:" + DateUtil.formatNow() + " 开始执行, ");ThreadUtil.sleep(11 * 1000);System.out.println(DateUtil.formatNow() + " 结束");i++;}};TimerTask task2 = new TimerTask() {private int i = 1;@Overridepublic void run() {System.out.print(i + "task2:" + DateUtil.formatNow() + " 开始执行, ");ThreadUtil.sleep(11 * 1000);System.out.println(DateUtil.formatNow() + " 结束");i++;}};Timer timer = new Timer("timer");timer.scheduleAtFixedRate(task1, 5000, 2000);timer.scheduleAtFixedRate(task2, 5000, 2000);
输出:1 task1:2022-10-31 16:58:27 开始执行, 2022-10-31 16:58:38 结束1 task2:2022-10-31 16:58:38 开始执行, 2022-10-31 16:58:49 结束2 task2:2022-10-31 16:58:49 开始执行, 2022-10-31 16:59:00 结束2 task1:2022-10-31 16:59:00 开始执行, 2022-10-31 16:59:11 结束3 task1:2022-10-31 16:59:11 开始执行, 2022-10-31 16:59:22 结束3 task2:2022-10-31 16:59:22 开始执行, 2022-10-31 16:59:33 结束4 task2:2022-10-31 16:59:33 开始执行, 2022-10-31 16:59:44 结束4 task1:2022-10-31 16:59:44 开始执行, 2022-10-31 16:59:55 结束
可以发现 , task1和task2其实都没有按照既定时间去执行任务了 。根本原因是在于,Timer内部仅维护一个线程执行所有TimerTask,为了避免错误 , 一个Timer对象最好仅调度一个TimerTask对象,除非可以确保多个TimerTask之间一定不会相互影响 。
因此编写TimerTask时应当自行捕获异常 。
五、取消任务Timer在创建时实际上是默认在内部维护了一个非守护线程,即使任务全部执行完成,线程也并不会销毁 。
Timer提供cancel()方法,可以手动调用取消定时器所有的任务,并销毁定时器 。
如果想要Timer内部创建的是守护线程,可以使用以下构造方法创建定时器,设置isDaemon为true:
- Timer(boolean isDaemon)
- Timer(String name, boolean isDaemon)
如果是要取消单个任务 , 可以使用TimerTask的cancel()方法 。
当TimerTask调用cancel之后,任务是取消了,但Timer自身并不能马上知道TimerTask被取消,而是在准备执行前才知道,因此Timer内部还维护着这个任务的引用 。若希望Timer立即清除引用,可调用Timer.purge()立即执行清除 。
推荐阅读
- 三 Java多线程-ThreadPool线程池
- 二 Java多线程-线程关键字
- 二 Java 编码那些事
- lol手游戏命师的大招怎么使用(lol手游技能释放技巧)
- 一 Java多线程-线程生命周期
- SpringBoot 常用注解的原理和使用
- 7 Java多线程:JUC(上)
- 一次 Java log4j2 漏洞导致的生产问题
- 眼霜的正确使用顺序,眼霜的正确使用方法
- 漫步者funbuds怎么配对_漫步者funbuds使用说明