定时器的实现原理就是新开一个子线程执行定时任务。
一、一次执行定时器。
一次执行定时器的时间如果在当前时间以前会立即执行任务,如果在未来时间,则会到指定的未来时间再执行任务。
示例代码:
public static void main(String[] args) {
try{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date dateRef = sdf.parse("2017-06-08 15:00:00");
new Timer().schedule(new TimerTask() {
@Override
public void run() {
System.out.println("我执行了,时间:" + new Date());
}
}, dateRef);;
} catch(ParseException e) {
e.printStackTrace();
}
}
输出结果:
我执行了,时间:Thu Jun 08 20:37:29 CST 2017
执行完后程序并不会停止,因为是新开的一个线程,新线程不是守护线程,所有主线程执行完毕子线程不会停止,要想让定时器执行完任务后立即停止,可以查看Timer类的构造方法:
// 无参构造
public Timer() {
this("Timer-" + serialNumber());
}
// 设置子线程是否为守护线程
public Timer(boolean isDaemon) {
this("Timer-" + serialNumber(), isDaemon);
}
// 给子线程起一个名字
public Timer(String name) {
thread.setName(name);
thread.start();
}
我们可以通过Timer(true)创建Timer对象设置子线程为守护线程,在任务执行完毕子线程立即退出。
二、无限次执行定时器
示例代码:
public static void main(String[] args) {
new Timer().schedule(new TimerTask() {
@Override
public void run() {
System.out.println("当前时间:" + new Date());
}
}, new Date(), 3000);
// 默认从当前时间开始,以 period 间隔时间无限次数执行某一任务
// new Timer().schedule(TimerTask task, long period);
// 以当前时间为参考时间,在此基础上延迟 delay 毫秒数,再以 period 间隔时间无限次数执行某一任务
// new Timer().schedule(TimerTask task, long delay, long period);
}
输出结果:
当前时间:Thu Jun 08 20:43:12 CST 2017
当前时间:Thu Jun 08 20:43:15 CST 2017
当前时间:Thu Jun 08 20:43:18 CST 2017
当前时间:Thu Jun 08 20:43:21 CST 2017
程序还在每隔3秒的执行一次并没有停止。
schedule方法的下一次执行任务的时间是从上一次的开始时间算起的,如果我们想从上一次的任务结束时间开始算起可以使用scheduleAtFixedRate方法,除了这一点外,schedule和scheduleAtFixedRate几乎没有其他区别。
定时器的执行是在一个队列内,如果队列前面一个任务的执行任务是很耗时的,可能导致后一个任务的执行并不是在指定的时间点执行,会被延后执行。
定时器也可以将自身从队列内移除,调用TimerTask类的cancel()方法可将自身从任务队列内移除,其他任务不受影响。当然cancel()方法有时候是不起作用的,只有当调用者TimerTask对象获取了任务队列queue的对象锁时才会真正的把自身从任务队列内移除。