不知道大家之前听说过定时调度没?如果没有听说过,这里我给大家几个小例子,如在2009-5-6 晚上12点发送一个电子邮件、每隔五分钟向控制台输出当前时间等。这些都是定时调度所涉及到的内容,今天我就给大家讲解下Java平台本身自带的定时调度类。这就是Timer和TimerTask,顾名思义,Timer为定时器而TimerTask则为定时任务。

在一般的情况下,我们也可以用Thread来实现一个定时调度的任务系统,如启动一个后台线程,然后里面的run方法是一个while(true)结构,接着使用Thread的sleep方法来定时休眠,就可以实现。不过对于定时任务,Java中已经提供了Timer类来帮助我们完成这个事情。

在进行讲解之前,首先给出个例子:

public class MainClass {      
         
    public static void main(String[] args) {      
        Timer timer = new Timer();      
        timer.schedule(new DisplayQuestionTask(), 0, 10 * 1000);      
        try {      
            Thread.sleep(10000);      
        } catch (InterruptedException e) {      
        }      
        timer.cancel();      
    }      
}      
     
class DisplayQuestionTask extends TimerTask {      
    int counter = 0;      
     
    public void run() {      
        System.out.println(counter++);      
    }      
}



执行上述代码的时候,大家可以看到,控制台并没有立即返回,而是等待了10秒才结束执行;并且在控制台里也输出了0,1两个数字。我想稍微的给大家讲解下这个代码。在main方法中,我们首先定义了一个Timer类,该类用于在后续代码中进行具体的时间调度,即每隔多少时间进行调度,调度是通过schedule方法来实现的,该方法有很多多态方法,给大家列举下:

void schedule(TimerTask task, Date time) //安排在指定的时间执行指定的任务。
          
void schedule(TimerTask task, Date firstTime, long period) //安排指定的任务在指定的时间开始进行重复的固定延迟执行。

void schedule(TimerTask task, long delay) // 安排在指定延迟后执行指定的任务。

void schedule(TimerTask task, long delay, long period) //安排指定的任务从指定的延迟后开始进行重复的固定延迟执行。



从上面的代码可以看出,可以在指定时间执行、可以在指定时间开始执行然后每隔固定时间循环执行、在固定延迟后执行一次调度、在固定延迟后执行一次然后每隔固定时间循环执行。我们上面的代码用的显然是第四种方式,在方法调用后的0秒后执行一次然后每隔10秒执行一次。这里注意下,Thread.sleep(10000);它的主要作用是防止主线程提前退出,给出一个修改后的代码,大家自己运行下:

public class MainClass {      
         
    public static void main(String[] args) {      
        Timer timer = new Timer();      
     
        timer.schedule(new DisplayQuestionTask(), 0, 10 * 1000);      
     
        /*try {    
            Thread.sleep(10000);    
        } catch (InterruptedException e) {    
        }*/     
        timer.cancel();      
    }      
}      
     
class DisplayQuestionTask extends TimerTask {      
    int counter = 0;      
     
    public void run() {      
        System.out.println(counter++);      
    }      
}



该代码与开始的代码的主要差别是,我将Thread.sleep(10000)注释掉了。大家执行后可以看出,代码会立即返回,控制台也没有任何输出。这里的主要原因是主线程没有等待,直接退出,导致程序退出。

这里稍微注意下,在Java应用中,只有主线程存在,其他的线程才能够存在;如果主线程退出了,那么程序就结束了。

然后在最后的语句中,我们调用了Timer的cancel方法,该方法的主要作用是终止计时器,并将所有的任务都放弃。

了解了这么多,给大家一个比较有用的调度任务,它调用了Java的垃圾收集器,用于定时进行垃圾回收,直接见代码:

public class MainClass {      
    public static void main(String[] args) {      
        Timer timer = new Timer();      
        GCTask task = new GCTask();      
        timer.schedule(task, 5000, 5000);      
        while (true) {      
            try {      
                Thread.sleep(500);      
            } catch (InterruptedException e) {      
            }      
        }      
    }      
}     
class GCTask extends TimerTask {   
    public void run() {   
        System.out.println("Running the scheduled task...");   
        System.gc();   
    }   
}

大家在执行本代码后,会发现控制台一直不返回,这个主要是通过while(true)实现的。然后在控制台上大家可以看到我们定义的输出。上面的代码完成的是每隔5秒执行一次垃圾回收,回收没在用的内存。注意,该代码只是要求Java垃圾回收器来回收内存,但并不是调用后Java垃圾收集器就会回收内存。

同时有一点没有提到,所有的定时任务都是继承自TimerTask,大家在使用的时候稍微注意点。

OK,学了今天的知识相信大家可以用Timer来完成自己需要的任务了。有一点,如果能让计算机去做的,尽量不要用人来做了,O(∩_∩)O哈哈~。充分发挥自己的想象力。顺便提一下,在开源领域有一个更为强大的调度框架,名字是QuartZ,有机会会给大家讲解。