02_传统定时器回顾
传统定时器使用Timer和TimerTask组合使用
java.util.Timer:定时器,用于指定时间后任务执行一次,或者定期重复执行。
java.util.TimerTask:继承了Runnable类,本质上就是一个Runnable对象
Timer和TimerTask定时器主要有两种使用情景:
1)多长时间后,执行一次定时器任务
2)多长时间后,执行一次定时器任务,之后每间隔相同时间执行一次任务
一、定时器的使用
package com.sam; import java.util.Date; import java.util.Timer; import java.util.TimerTask; /** * 传统定时器回顾 * @author SAM * */ public class TraditionalTimerTask { /** * @param args */ public static void main(String[] args) { Timer timer = new Timer(); timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { System.out.println("定时器 TName=" + Thread.currentThread().getName() + ",bombing!"); } }, 1000L, 3000L); // 为了观察,打印当前时间 while (true){ System.out.println(new Date().toLocaleString()); try { Thread.sleep(1000L); } catch (InterruptedException e) { e.printStackTrace(); } } } }
执行结果:
2017-5-13 17:23:30
定时器 TName=Timer-0,bombing!
2017-5-13 17:23:32
2017-5-13 17:23:33
2017-5-13 17:23:34
定时器 TName=Timer-0,bombing!
2017-5-13 17:23:35
2017-5-13 17:23:36
2017-5-13 17:23:37
定时器 TName=Timer-0,bombing!
2017-5-13 17:23:38
2017-5-13 17:23:39
2017-5-13 17:23:40
定时器 TName=Timer-0,bombing!
可以看到定时器首次1秒后执行,之后每间隔3秒都会重复执行一次定时器任务。
二、定时器巩固
需求:2秒后执行一次任务,接着4秒后执行一次任务,然后又回到2秒后执行一次任务,
紧接着4秒又执行一次任务,如此反复,请写出代码。
package com.sam; import java.util.Date; import java.util.Timer; import java.util.TimerTask; /** * 传统定时器回顾 * 需求:2秒后执行一次任务,接着4秒后执行一次任务,然后又回到2秒后执行一次任务, * 紧接着4秒又执行一次任务,如此反复,请写出代码。 * @author SAM * */ public class TraditionalTimerTask_2 { /** * @param args */ public static void main(String[] args) { // 2秒后执行定时任务 new Timer().schedule(new MyTimerTask(), 2000L); // 为了观察,打印当前时间 while (true){ System.out.println(new Date().toLocaleString()); try { Thread.sleep(1000L); } catch (InterruptedException e) { e.printStackTrace(); } } } } class MyTimerTask extends TimerTask{ static int count; @Override public void run() { // 奇数4秒,偶数2秒 count = ++count % 2; System.out.println("定时器 TName=" + Thread.currentThread().getName() + ",bombing!"); new Timer().schedule(new MyTimerTask(), 2000L + 2000L*count); } }
执行结果:
2017-5-13 17:45:52
2017-5-13 17:45:53
定时器 TName=Timer-0,bombing!
2017-5-13 17:45:54
2017-5-13 17:45:55
2017-5-13 17:45:56
2017-5-13 17:45:57
定时器 TName=Timer-1,bombing!
2017-5-13 17:45:58
2017-5-13 17:45:59
定时器 TName=Timer-2,bombing!
2017-5-13 17:46:00
2017-5-13 17:46:01
2017-5-13 17:46:02
2017-5-13 17:46:03
定时器 TName=Timer-3,bombing!
接着再深入Timer类一些细节,Timer有两组启动定时器任务的方法,他们可能比较费解:
1)schedule(TimerTask task, long delay, long period)
2)scheduleAtFixedRate(TimerTask task, long delay, long period)
区别:
他们都可以实现:多长时间后,执行一次定时器任务,之后每间隔相同时间执行一次任务;
但是他们又有一些本质的区别,首先schedule是固定延期执行,而scheduleAtFixedRate是固定速率执行。
再具体说:
1)固定延期,根据前一次执行的实际时间来安排每一次执行。
如果由于任何原因(如垃圾回收或者其他后台活动)而延迟了某次执行,则后续执行也将延迟。
2)固定速率,根据已安排的初始执行时间来安排每次执行。
如果由于任何原因(如垃圾回收或者其他后台活动)而延迟了某次执行,
则将快速连续执行两次或者更多任务,从而使后续执行能够“追赶上来”。
注意这时TimerTask的执行需要考虑同步。
最后推荐一个开源项目,quartz,主要用来实现复杂的调度需求。
例如周一至周五早上10点定时收邮件,周六日不收邮件,
这时使用Timer和TimerTask可能比较复杂,使用quartz开源项目可以很容易的解决这类需求。
上一篇: 定时任务的防止重复执行
下一篇: Spring定时任务的几种实现