一、定时器Timer的使用
Timer类的主要作用就是设置计划任务,封装任务的是TimeTask类,这是一个抽象类
1.方法shedule(TimeTask task,Date time)
该方法的作用是在指定的日期执行一个任务
package com.zqj.timer;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class Test1 {
public static void main(String[] args) {
System.out.println("当前时间为:" + new Date());
Calendar calendarRef = Calendar.getInstance();
calendarRef.add(Calendar.SECOND,10);
Date runDate = calendarRef.getTime();
MyTask task = new MyTask();//设置任务
Timer timer = new Timer();//使用Timer类设置计划任务
//Timer timer = new Timer(true);//守护线程
timer.schedule(task,runDate);//timer类的方法
}
}
class MyTask extends TimerTask{
@Override
public void run() {
System.out.println("任务执行了,时间为:" + new Date());
}
}
执行结果:
每创建一个Timer就启动一个新线程。
TimeTask是以队列的方式一个个被顺序的执行,所以执行时间可能和预期不一致。因为前面可能有任务消耗的时间很长,导致后面任务的时间被延后。比如有A,B两个任务需要被执行,B设置延迟10秒执行,A执行时长为20秒。因此B任务不会再10秒后执行,而是在A任务执行后立即执行。
2.方法schedule(TimeTask task,Date firstTime,long period)
package com.zqj.timer;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class Test1 {
public static void main(String[] args) {
System.out.println("当前时间为:" + new Date());
Calendar calendarRef = Calendar.getInstance();
calendarRef.add(Calendar.SECOND,10);
Date runDate = calendarRef.getTime();
MyTask task = new MyTask();
Timer timer = new Timer();
//Timer timer = new Timer(true);//守护线程
timer.schedule(task,runDate,4000);
}
}
class MyTask extends TimerTask{
@Override
public void run() {
System.out.println("任务执行了,时间为:" + new Date());
}
}
执行结果:每隔4秒执行一次任务
1)TimeTask类的cancel()方法
该类的作用是将自身从任务队列中进行清除,是写在TimeTask类中的;使用方法为this.cancel()
2)Timer类的cancel()方法
该方法是清除任务队列中的所有任务,使用方法为timer.calcel();
注意事项:Timer类的cancel()方法又是不一定会停止计划任务,而是正常执行,原因是有时cancel()方法没有争抢到queue锁,则让TimeTask类中的任务正常执行
3.方法schedule(TimeTask task,long delay)
该方法的作用是以执行schedule(TimeTask task,long delay)方法当前时间为参考时间,在此基础上延迟指定的毫秒数后执行一次TimerTask任务
package com.zqj.timer;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class Test2 {
public static void main(String[] args) {
Task task = new Task();
Timer timer = new Timer();
System.out.println("当前时间为:"+new Date());
timer.schedule(task,7000);
}
}
class Task extends TimerTask{
@Override
public void run() {
System.out.println("运行了!时间为:"+ new Date());
}
}
执行结果:任务task被延迟了7秒执行
4.方法schedule(TimeTask task,long delay,long period)
该方法的作用是以执行schedule(TimeTask task,long delay)方法当前时间为参考时间,在此基础上延迟指定的毫秒数后执行一次TimerTask任务,再以某一间隔时间无限次数的执行某个任务
5.方法scheduleAtFixedRate(TimerTask task,Date firstTime,long period)
方法schedule和scheduleAtFixedRate都会按顺序执行,所以不用考虑非线程安全的情况;两者的主要区别只在于有没有追赶特性。
package com.zqj.timer;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class Test4 {
public static void main(String[] args) {
TaskAtFixedRate task = new TaskAtFixedRate();
System.out.println("现在执行时间:"+new Date());
Calendar calendarRef = Calendar.getInstance();
calendarRef.set(Calendar.SECOND,calendarRef.get(Calendar.SECOND)-10);
Date runDate = calendarRef.getTime();
System.out.println("计划执行时间:"+runDate);
Timer timer = new Timer();
timer.scheduleAtFixedRate(task,runDate,4000);
}
}
class TaskAtFixedRate extends TimerTask{
@Override
public void run() {
System.out.println("begin time=" +new Date());
System.out.println("end time=" +new Date());
}
}
执行结果:
上面代码任务开始时间和当前时间间隔10秒,任务4秒执行一次,在启动程序时,任务直接先跑了三次(10/4向上取整)。追赶性就是如果我们设置任务开始的时间在当前时间之前,那么他会计算出两个时间的差,计算出时间差内能够执行任务多少次,然后立即执行。而shedule方法在这段时间是不执行任务的。