昨夜星辰昨夜风,画楼西畔桂堂东
在JDK库中,Timer类主要负责计划任务的功能,也就是在指定时间开始执行某一个任务,Timer类方法列表如下所示:
Timer类的主要作用就是设置计划任务,但封装任务的类却是TimerTask类,类结构如下所示:
执行计划任务的代码要放入TimerTask的子类中,因为TimerTask是一个抽象类。
下面介绍并测试几个常用的方法:
- 方法schedule(TimerTask task, Date time):该方法的作用是在指定的日期执行一次某一任务。
测试代码:
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
public static void main(String[] args) {
System.out.println("当前时间为:" + new Date());
Calendar instance = Calendar.getInstance();
instance.add(Calendar.SECOND , 10); //设置时间为10秒之后
Date time = instance.getTime();
MyTask myTask = new MyTask();
Timer timer = new Timer();
timer.schedule(myTask,time);
}
}
class MyTask extends TimerTask {
@Override
public void run() {
System.out.println("任务执行时间:" + new Date());
}
}
运行结果:
但是这里,你应该注意到,任务已经执行了,但是程序还没有停下来。我们来看下在创建Timer对象时的源码:
/**
* Creates a new timer. The associated thread does <i>not</i>
* {@linkplain Thread#setDaemon run as a daemon}.
*/
public Timer() {
this("Timer-" + serialNumber());
}
//这个构造方法调用的是如下的构造方法
/**
* Creates a new timer whose associated thread has the specified name.
* The associated thread does <i>not</i>
* {@linkplain Thread#setDaemon run as a daemon}.
*
* @param name the name of the associated thread
* @throws NullPointerException if {@code name} is null
* @since 1.5
*/
public Timer(String name) {
thread.setName(name);
thread.start();
}
由此可知,创建一个Timer就是启动了一个线程,由于这个启动的线程不是守护线程,所以一直在运行。下面将新创建的Timer类改成守护线程:
只需要将上面的 Timer timer = new Timer();
改为 Timer timer = new Timer(true);
即可,再来看看运行结果:
可以看到,程序运行后迅速结束了当前的线程,并且TimerTask中任务也没有被运行,因为进程已经结束。
并且,如果计划的时间早于当前时间,则立即执行task任务;
- 方法 schedule(TimerTask task, Date firstTime,long period):该方法的作用是在指定的日期之后按指定的间隔周期,无线循环的执行某一任务。
测试代码:
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
public static void main(String[] args) {
System.out.println("当前时间为:" + new Date());
Calendar instance = Calendar.getInstance();
instance.add(Calendar.SECOND , 10); //设置时间为10秒之后
Date time = instance.getTime();
MyTask myTask = new MyTask();
Timer timer = new Timer();
timer.schedule(myTask,time,2000);
}
}
class MyTask extends TimerTask {
@Override
public void run() {
System.out.println("任务执行时间:" + new Date());
}
}
运行结果:
从运行结果可以看出,任务每2秒被执行一次,而且还是无限期重复执行的。
- 方法 schedule(TimerTask task,long delay):该方法的作用是以执行schedule(TimerTask task,long delay)方法当前的时间为参考时间,在此基础上延迟指定的毫秒数后执行一次TimerTask任务。
测试代码:
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
public static void main(String[] args) {
System.out.println("当前时间为:" + new Date());
// Calendar instance = Calendar.getInstance();
// instance.add(Calendar.SECOND , 10); //设置时间为10秒之后
// Date time = instance.getTime();
MyTask myTask = new MyTask();
Timer timer = new Timer();
timer.schedule(myTask,2000);
}
}
class MyTask extends TimerTask {
@Override
public void run() {
System.out.println("任务执行时间:" + new Date());
}
}
运行结果:
由此可知,任务被延迟2秒执行了。
- 方法schedule(TimerTask task,long delay,long period):该方法的作用是以执行schedule(TimerTask task,long delay,long period)方法当前的时间为参考时间,在此时间基础上延迟指定的毫秒数,再以某一间隔时间无限次数地执行某一任务。
测试代码:
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
public static void main(String[] args) {
System.out.println("当前时间为:" + new Date());
// Calendar instance = Calendar.getInstance();
// instance.add(Calendar.SECOND , 10); //设置时间为10秒之后
// Date time = instance.getTime();
MyTask myTask = new MyTask();
Timer timer = new Timer();
timer.schedule(myTask,3000,2000);
}
}
class MyTask extends TimerTask {
@Override
public void run() {
System.out.println("任务执行时间:" + new Date());
}
}
运行结果:
在当前时间3秒过后,以每2秒的周期执行任务。
- 方法scheduleAtFixedRate(TimerTask task,Date firstTime,long period):方法scheduleAtFixedRate和schedule主要的区别只在于有没有追赶特性:
验证schedule方法不具备追赶执行性,测试代码:
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
public static void main(String[] args) {
MyTask myTask = new MyTask();
System.out.println("当前时间为:" + new Date());
Calendar instance = Calendar.getInstance();
instance.set(Calendar.SECOND , instance.get(Calendar.SECOND) -10); //设置时间为10秒之前
Date time = instance.getTime();
System.out.println("计划执行时间:" + time);
Timer timer = new Timer();
timer.schedule(myTask,time,2000);
}
}
class MyTask extends TimerTask {
@Override
public void run() {
System.out.println("begin time" + new Date());
System.out.println("end time" + new Date());
}
}
运行结果:
从时间上可以看出来,59分10秒到59分20秒之间的任务都没有执行,所以,schedule不具备追赶特性。
验证scheduleAtFixedRate有追赶特性,测试代码:
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
public static void main(String[] args) {
MyTask myTask = new MyTask();
System.out.println("当前时间为:" + new Date());
Calendar instance = Calendar.getInstance();
instance.set(Calendar.SECOND , instance.get(Calendar.SECOND) -10); //设置时间为10秒之前
Date time = instance.getTime();
System.out.println("计划执行时间:" + time);
Timer timer = new Timer();
// timer.schedule(myTask,time,2000);
timer.scheduleAtFixedRate(myTask,time,2000);
}
}
class MyTask extends TimerTask {
@Override
public void run() {
System.out.println("begin time" + new Date());
System.out.println("end time" + new Date());
}
}
运行结果:
可以看出,在01分44秒到01分54秒之间的任务都被“补充性”的执行了,所以,scheduleAtFixedRate具备追赶特性。