一、简介
Timer 是一个定时器工具,用来在一个后台线程计划执行指定任务。它可以计划执行一个任务一次或反复多次。TimerTask 是一个抽象类,它的子类代表一个可以被 Timer 计划的任务。
定时器 Timer 内部使用多线程方式处理。
二、方法介绍
2.1 schedule(TimerTask task,Date time)
在指定的日期执行一次某一任务,试运行代码如下:
public class MyTask extends TimerTask{
public void run(){
System.out.println("我是需要执行的定时任务"+new Date());
}
public static void main(String args[]){
System.out.println("当前时间为"+new Date());
Calendar calendar = Calendar.getInstance();
/*执行完当前时间之后,未来的10s执行*/
calendar.add(Calendar.SECOND,10);
Date date = calendar.getTime();
MyTask task = new MyTask();
Timer timer = new Timer();
timer.schedule(task,date);
}
}
输出结果如下所示,我们发现 eclipse 的任务还未销毁,呈红色状态,因为创建一个 Timer 就是启动一个线程,这个线程不是守护线程,所以会一直运行。
如果将 Timer 改成守护线程即:Timer timer = new Timer(true)。则打印完当前时间就停止了,不会执行 task 的任务。如果有多个 TimerTask 任务及延时测试,则以队列的方式一个一个被顺序性地执行,因为前面的任务有可能消耗的时间较长,所以执行的时间和预期的时间很可能不一致。
2.2 schedule(TimerTask task,Date firstTime,long period)
在指定的日期之后按指定的间隔周期,无限循环的执行某一任务,试运行代码如下:
public class MyTask extends TimerTask{
public void run(){
System.out.println("我是需要执行的定时任务"+new Date());
}
public static void main(String args[]){
System.out.println("当前时间为"+new Date());
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND,10);//执行完当前时间之后,未来的10s执行
Date date = calendar.getTime();
MyTask task = new MyTask();
Timer timer = new Timer();
timer.schedule(task,date,4000);
}
}
输出结果如下:
2.3 cancel()
将自身从任务队列中进行清除,试运行代码如下:
public class MyTask extends TimerTask{
public void run(){
System.out.println("我是需要执行的定时任务"+new Date());
this.cancel();
System.out.println("我已经移除了自己的定时任务");
}
public static void main(String args[]){
System.out.println("当前时间为"+new Date());
Calendar calendar = Calendar.getInstance();
Date date = calendar.getTime();
MyTask task = new MyTask();
Timer timer = new Timer();
timer.schedule(task,date,4000);
}
}
输出结果如下,我们发现:代码则只执行一次,就不在循环执行了,其他的 TimerTask 不受任何影响。
还可以使用 cancle() 方法将任务队列中全部的任务进行清空,试运行代码如下:
public class MyTaskB extends TimerTask{
public void run(){
System.out.println("我是需要执行的定时任务B"+new Date());
}
}
public class MyTaskA extends TimerTask{
public void run(){
System.out.println("我是需要执行的定时任务A"+new Date());
}
public static void main(String args[]){
System.out.println("当前时间为"+new Date());
Calendar calendar = Calendar.getInstance();
Date date = calendar.getTime();
MyTaskA taskA = new MyTaskA();
MyTaskB taskB = new MyTaskB();
Timer timer = new Timer();
timer.schedule(taskA,date,4000);
timer.schedule(taskB,date,4000);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
timer.cancel();
}
}
输出结果如下,我们发现程序只执行 10s 的循环任务,然后全部任务被清除,并且进程被销毁,按钮由红色变为灰色。
注意:Timer 的 cancel() 方法有时不一定会停止计划任务,而是正常执行。因为 canel() 方法有时没有争抢到 queue 锁,则让 TimerTask 类中的任务正常执行。
2.4 schedule(TimerTask task,long delay)
以执行此方法当前的时间为参考时间,在此时间的基础上延迟指定的毫秒数后执行一次 TimerTask 任务,试运行代码如下:
public class MyTaskA extends TimerTask{
public void run(){
System.out.println("我是需要执行的定时任务A"+new Date());
}
public static void main(String args[]){
MyTaskA taskA = new MyTaskA();
Timer timer = new Timer();
System.out.println("当前时间为"+new Date());
/*任务被延迟7s执行了*/
timer.schedule(taskA,7000);
}
}
输出结果如下,我们发现,任务呗延迟 7s 执行了。
2.5 schedule(TimerTask task,long delay,long period)
以执行此方法当前的时间为参考时间,在此时间的基础上延迟指定的毫秒数后执行一次 TimerTask 任务,再以某一时间间隔无限次的执行某一任务,试运行代码如下:
public class MyTaskA extends TimerTask{
public void run(){
System.out.println("我是需要执行的定时任务A"+new Date());
}
public static void main(String args[]){
MyTaskA taskA = new MyTaskA();
Timer timer = new Timer();
System.out.println("当前时间为"+new Date());
timer.schedule(taskA,7000,1000);
}
}
输出结果如下,我们发现在延迟了 7s 之后,任务以 1s 为时间间隔依次执行。
2.6 scheduleAtFixedRate(TimerTask task,Date firstTime,long period)
此方法和 schedule() 方法都会顺序的执行,只是 scheduleAtFixedRate 具有追赶性。
schedule() 方法情况一:MyTask 里面睡 1s,主线程 timer.schedule(task,马上,3000),没有延时,第一次马上执行,第二次粗略的认为 3s 执行一次。
public class MyTaskA extends TimerTask{
public void run(){
System.out.println("我是需要执行的定时任务A"+new Date());
}
public static void main(String args[]){
MyTaskA taskA = new MyTaskA();
Timer timer = new Timer();
System.out.println("当前时间为"+new Date());
try {
Thread.sleep(1000);
timer.schedule(taskA,0,3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
schedule() 方法情况二:MyTask 里面睡 1s,主线程 timer.schedule(task,3000,4000),没有延时,第一次延迟 3s 执行, 第二次 4s 后执行。
public class MyTaskA extends TimerTask{
public void run(){
System.out.println("我是需要执行的定时任务A"+new Date());
}
public static void main(String args[]){
MyTaskA taskA = new MyTaskA();
Timer timer = new Timer();
System.out.println("当前时间为"+new Date());
try {
Thread.sleep(1000);
timer.schedule(taskA,3000,4000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
schedule() 方法情况三:MyTask 里面睡 5s,主线程 timer.schedule(task,马上,2000),有延时,第一次马上执行,第二次 5s 后执行
public class MyTaskA extends TimerTask{
public void run(){
System.out.println("我是需要执行的定时任务A"+new Date());
}
public static void main(String args[]){
MyTaskA taskA = new MyTaskA();
Timer timer = new Timer();
System.out.println("当前时间为"+new Date());
try {
Thread.sleep(5000);
timer.schedule(taskA,0,2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
schedule() 方法情况四:MyTask 里面睡 5s,主线程 timer.schedule(task,3000,2000),有延时,第一次延迟 3s 执行,第二次 5s 后执行。
public class MyTaskA extends TimerTask{
public void run(){
System.out.println("我是需要执行的定时任务A"+new Date());
}
public static void main(String args[]){
MyTaskA taskA = new MyTaskA();
Timer timer = new Timer();
System.out.println("当前时间为"+new Date());
try {
Thread.sleep(5000);
timer.schedule(taskA,3000,2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
2.6 scheduleAtFixedRate()
scheduleAtFixedRate() 方法情况一:MyTask 里面睡 1s,主线程 timer.scheduleAtFixedRate(task,马上,3000),没有延时,第一次马上执行,第二次粗略的认为 3s 执行一次。
public class MyTaskA extends TimerTask{
public void run(){
System.out.println("我是需要执行的定时任务A"+new Date());
}
public static void main(String args[]){
MyTaskA taskA = new MyTaskA();
Timer timer = new Timer();
System.out.println("当前时间为"+new Date());
try {
Thread.sleep(1000);
timer.scheduleAtFixedRate(taskA,0,3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
scheduleAtFixedRate() 方法情况二:MyTask里面睡 1s,主线程 timer.scheduleAtFixedRate(task,3000,4000), 没有延时,第一次延迟 3s 执行, 第二次 4s 后执行。
public class MyTaskA extends TimerTask{
public void run(){
System.out.println("我是需要执行的定时任务A"+new Date());
}
public static void main(String args[]){
MyTaskA taskA = new MyTaskA();
Timer timer = new Timer();
System.out.println("当前时间为"+new Date());
try {
Thread.sleep(1000);
timer.scheduleAtFixedRate(taskA,3000,4000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
scheduleAtFixedRate() 方法情况三:MyTask 里面睡 5s,主线程 timer.scheduleAtFixedRate(task,马上,2000),有延时,第一次马上执行,第二次 5s 后执行。
public class MyTaskA extends TimerTask{
public void run(){
System.out.println("我是需要执行的定时任务A"+new Date());
}
public static void main(String args[]){
MyTaskA taskA = new MyTaskA();
Timer timer = new Timer();
System.out.println("当前时间为"+new Date());
try {
Thread.sleep(5000);
timer.scheduleAtFixedRate(taskA,0,2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
scheduleAtFixedRate() 方法情况四:MyTask 里面睡 5s,主线程 timer.scheduleAtFixedRate(task,3000,2000),有延时,第一次延迟 3s 执行,第二次 5s 后执行。
public class MyTaskA extends TimerTask{
public void run(){
System.out.println("我是需要执行的定时任务A"+new Date());
}
public static void main(String args[]){
MyTaskA taskA = new MyTaskA();
Timer timer = new Timer();
System.out.println("当前时间为"+new Date());
try {
Thread.sleep(5000);
timer.scheduleAtFixedRate(taskA,3000,2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
总结:这两个方法在运行效果上没有任何区别,但是 schedule() 方法没有追赶性, scheduleAtFixedRate() 方法具有追赶性。
public class MyTask extends TimerTask{
public void run() {
System.out.println("begin任务,我的执行时间为"+System.currentTimeMillis());
System.out.println("end任务, 我的执行时间为"+System.currentTimeMillis());
}
public static void main(String[] args) {
MyTask myTask = new MyTask();
System.out.println("现在执行时间为"+System.currentTimeMillis());
Calendar c = Calendar.getInstance();
c.set(Calendar.SECOND, c.get(Calendar.SECOND)-20);
System.out.println("计划执行时间为"+c.getTime().getTime());
Timer timer = new Timer();
/*因为需要提前执行,中间有20s的时间差,如果是schelude()方法,则这时间段的任务就不执行了,直接从当前时间开始往下执行*/
timer.schedule(myTask,c.getTime(), 1000);
/*scheduleAtFixedRate方法则要追赶这20s的时间差,以当前时间执行好多次,即时间相同的任务,然后继续往下执行*/
timer.scheduleAtFixedRate(myTask,c.getTime(), 1000);
}
}