TimerTask是一个实现了Runnable接口的抽象类,代表一个可以被Timer执行的任务。它有一个抽象方法run()----计时器任务要执行的操作。因此,每个具体的任务类都必须继承TimerTask类,并且重写run()方法。
在JDK中的定义如下:
Timer类的方法:
void cancel() 终止此计时器,丢弃所有当前已安排的任务。
int purge() 从此计时器的任务队列中移除所有已取消的任务。
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) 安排指定的任务从指定的延迟后开始进行重复的固定延迟执行。
void scheduleAtFixedRate(TimerTask task, Date firstTime, long period) 安排指定的任务在指定的时间开始进行重复的固定速率执行。
void scheduleAtFixedRate(TimerTask task, long delay, long period) 安排指定的任务在指定的延迟后开始进行重复的固定速率执行。
TimerTask 类的方法:
boolean cancel() 取消此计时器任务。
abstract void run() 此计时器任务要执行的操作。
long scheduledExecutionTime() 返回此任务最近实际 执行的已安排 执行时间。
import
java.util.TimerTask;
public
class
TaskA
extends
TimerTask{
private
int
id;
public
TaskA (
int
id){
this
.id = id;
}
@Override
public
void
run() {
System.out.println(
"start run taskA ; id =
" + id
);
}
}
import
java.util.Date;
import
java.util.Timer;
public
class
Test1 {
public
static
void
main(String[] args) {
Timer timer =
new
Timer();
timer.schedule(
new
TaskA (
1
),
5000
);
// 5秒后启动任务
TaskA secondTask=
new
TaskA (
2
);
timer.schedule(secondTask,
1000
,
3000
);
// 1秒后启动任务,以后每隔3秒执行一次线程
Date date =
new
Date();
timer.schedule(
new
TaskA (
3
),
new
Date(date.getTime()+
1000
));
//以date为参数,指定某个时间点执行线程 ,一秒后执行,执行一次
System.out.println(
"end in main thread..."
);
}
}
不管任务执行耗时是否大于间隔时间,scheduleAtFixedRate和scheduleWithFixedDelay都不会导致同一个任务并发地被执行。唯一不同的是scheduleWithFixedDelay是当前一个任务结束的时刻,开始结算间隔时间,如0秒开始执行第一次任务,任务耗时5秒,任务间隔时间3秒,那么第二次任务执行的时间是在第8秒开始。
ScheduledExecutorService的实现类,是ScheduledThreadPoolExecutor。ScheduledThreadPoolExecutor对象包含的线程数量是没有可伸缩性的,只会有固定数量的线程。不过你可以通过其构造函数来设定线程的优先级,来降低定时任务线程的系统占用。
特别提示:通过ScheduledExecutorService执行的周期任务,如果任务执行过程中抛出了异常,那么过ScheduledExecutorService就会停止执行任务,且也不会再周期地执行该任务了。所以你如果想保住任务都一直被周期执行,那么catch一切可能的异常。