在JDK中,Timer类的主要作用是设置计划任务,即在指定时间执行某个任务,它在内部使用多线程的方式进行处理,与Java多线程技术有着非常大的关联。
以下为Timer类的简单使用示例
public class TimerTest {
public static void main(String[] args) throws InterruptedException {
Timer timer=new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("任务已执行完毕.......");
}
},new Date(System.currentTimeMillis()+10000));
Thread.sleep(20000);
timer.cancel();
}
}
任务已执行完毕…
该使用示例中使用了Timer类中的schedule( )方法,通过这个方法可以在指定时间执行某一个任务。该示例中schedule( )方法的参数为 schedule(TimerTask task, Date time),其中TimeTask类用于定义需要执行的任务,Date用于指定日期。
schedule( )还有很多重载方法,例如:
- schedule(TimerTask task, Date Time, long delay),该方法可以让任务延时一段时间再执行。
- schedule(TimerTask task, Date firstTime, long period),该方法可以实现按指定间隔周期无线循环的执行某一任务。如以下代码所示:
public class TimerTest {
public static void main(String[] args) throws InterruptedException {
Timer timer=new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("任务执行......."+"执行时间为"+System.currentTimeMillis());
}
},new Date(System.currentTimeMillis()+1000),1000);
}
}
任务执行…执行时间为1638709176118
任务执行…执行时间为1638709177206
任务执行…执行时间为1638709178232
任务执行…执行时间为1638709179248
任务执行…执行时间为1638709180254
当创建Timer对象时,会启动一个非守护线程TimerThread,线程的作用是执行定时任务。该线程会一直运行,只有执行了Timer类中的cancel( )时,TimerThread线程才会被销毁。
TimerTask是以队列的方式逐一按顺序执行的。每一个Timer实例中都有一个TaskQueue,用于存放TimerTask,当执行schedule方法时,TimerTask实例参数会被存入Timer类中的TaskQueue中。TimerThread线程会对TaskQueue中的TimerTask进行执行处理。
Timer类中,TaskQueue会以锁的形式在操作TaskQueue的方法中出现,也就是各个线程对于TaskQueue的操作是互斥的,以此来保证线程安全。
如果任务的计划执行时间早于当前时间,则任务会立即执行。如以下代码所示
public class TimerTest {
public static void main(String[] args) throws InterruptedException {
Timer timer=new Timer();
long executeTime=System.currentTimeMillis()-1000;
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("任务执行......."+"执行时间为"+System.currentTimeMillis());
}
},new Date(executeTime));
System.out.println("当前时间:"+System.currentTimeMillis());
System.out.println("计划预定执行时间:"+executeTime);
}
}
当前时间:1638709415468
任务执行…执行时间为1638709415468
计划预定执行时间:1638709414468
对于需要循环执行的任务,Timer类中还提供一种方法 scheduleAtFixedRate( ),该方法与schedule方法的使用方式是一样的,那么两者之间有什么不同呢?
scheduleAtFixedRate( )与schedule( )的区别在于,对于一个需要循环执行的任务,如果任务的实际开始时间与期望开始时间间隔之中,任务已需要循环执行多次但并未被执行,schedule会把这些未执行任务取消执行,而scheduleAtFixedRate会在任务实际开始之后,短时间内无间隔的补充执行这些未执行的任务。
这就是scheduleAtFixedRate( )对于任务的执行的追赶特性。而schedule( )没有追赶特性。