TimerTask是一种特殊的线程,用来为Timer安排一次执行或重复执行的任务。它实现了Runnable接口,是一个抽象类:
/**
* A task that can be scheduled for one-time or repeated execution by a Timer.
*
* @author Josh Bloch
* @see Timer
* @since 1.3
*/
public abstract class TimerTask implements Runnable{...}
它本身没有实现run()函数,因此需要子类来实现它。所以有了以下的实现方式:
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestTimerTask extends TimerTask {
@Override
public void run() {
System.out.println(new Date());
}
public static void main(String[] args) throws InterruptedException {
Timer timer = new Timer();
//TimerTask
TestTimerTask TTT = new TestTimerTask();
//timer.schedule(TTT, 1000, 1000);
timer.schedule(TTT, new Date(), 1000);
Thread.sleep(8000L);
timer.cancel();
//创建线程池
ExecutorService es=Executors.newCachedThreadPool();
}
}
定时器任务与线程不同,它是定时执行的线程,因此不能够直接使用start()来启动它,而需要使用一个特殊的类Timer来启动它。Timer是一种工具,用来安排在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行。
与每个Timer对象相对应的是单个后台线程,用于顺序地执行所有计时器任务.计时器任务应该迅速完成。如果完成某个计时器任务的时间太长,那么它会“独占”计时器的任务执行线程。因此,这就可能延迟后续任务的执行,而这些任务就可能“堆在一起”,并且在上述不友好的任务最终完成时才能够被快速连续地执行。
对Timer对象最后的引用完成后,并且所有未处理的任务都已执行完成后,计时器的任务执行线程会正常终止(并且成为垃圾回收的对象)。但是这可能要很长时间后才发生。在默认情况下,任
务执行线程并不作为守护线程来运行,所以它能够阻止应用程序终止。如果调用者想要快速终止计时器的任务执行线程,那么调用者应该调用计时器的cancel方法。
public void cancel() {
...
}
如果意外终止了计时器的任务执行线程,例如调用了它的stop方法,那么所有以后对该计时器安排任务的尝试都将导致IllegalStateException,就好像调用了计时器的cancel方法一样。
此类是线程安全的:多个线程可以共享单个Timer对象而无须进行外部同步。此类可扩展到大量同时安排的任务(存在数千个都没有问题)。在内部中,它使用二进制堆来表示其任务队列,所以安排任务的开销是O(logn),其中n是同时安排的任务数。
Timer运行定时器的方式有如下几种。
1、安排在指定的时间执行指定的任务:
public void schedule(TimerTask task, Date time)
2、安排指定的任务在指定的时间开始进行重复的固定延迟执行:
public void schedule(TimerTask task, Date firstTime, long period)
3、安排在指定延迟后执行指定的任务:
public void schedule(TimerTask task, long delay)
4、安排指定的任务从指定的延迟后开始进行重复的固定延迟执行:
public void schedule(TimerTask task, long delay, long period)
5、安排指定的任务在指定的时间开始进行重复的固定速率执行:
public void scheduleAtFixedRate(TimerTask task, Date firstTime,long period)
6、安排指定的任务在指定的延迟后开始进行重复的固定速率执行:
public void scheduleAtFixedRate(TimerTask task, long delay, long period)
例如,我们可以使用下例循环执行定时器任务,执行的间隔为1000ms:
Timer timer = new Timer();
TestTimerTask TTT = new TestTimerTask();
timer.schedule(TTT, 1000, 1000);
其中的第一个参数1000表示延迟执行的时间,第二个参数表示循环执行的时间,单位均为毫秒(ms)。这样,在系统启动1000ms后才会执行定时器任务,并且每过1000ms都会继续重新执行该任务。程序运行的结果为:
Tue Dec 26 09:53:51 CST 2017
Tue Dec 26 09:53:52 CST 2017
Tue Dec 26 09:53:53 CST 2017
Tue Dec 26 09:53:54 CST 2017
Tue Dec 26 09:53:55 CST 2017
Tue Dec 26 09:53:56 CST 2017
Tue Dec 26 09:53:57 CST 2017
Tue Dec 26 09:53:58 CST 2017
Tue Dec 26 09:53:59 CST 2017