定时任务主要用到两个类,一个是Timer类,一个是TimerTask类。Timer类主要用于维护定时任务,管理任务的执行,TimerTask是具体执行任务的类。Timer类的schedule方法可以设置任务的运行时机,TimerTask抽象类中有run抽象方法,我们需要实际运行的任务代码就是放在这里。
Timer是一个类,用来管理java代码中需要依靠时间条件控制执行的方法,比如定时执行,定间隔时间执行等等。
Timer定时常用的有schedule方法和scheduleFixedRate方法:这两种方法非常相似,基本逻辑:
1. 接收到需要执行的任务task,首次执行时间time,时间间隔period;
2. 将time和period赋值给task的对应属性nextExecutionTime、period;
3. 将task任务加入queue队列
2. TimerTask类因为实现了Runable接口,即创建了线程,所以会在满足条件的时候就会执行线程。
Timer类Timer类中定义的两个变量:任务队列和时间线程。
private final TaskQueue queue = new TaskQueue(); private final TimerThread thread = new TimerThread(queue);
TaskQueue中定义了TimerTask[]类型的变量,初始长度是128.用于存放TimerTask;
TimerThread是继承了Thread的线程类,在这个类中有一个有参构造方法,用来获取TaskQueue类型的queue任务队列,里面的run方法就是要执行的方法:
private TaskQueue queue;
TimerThread(TaskQueue queue) {
this.queue = queue;
}
public void run() {
try {
mainLoop();
} finally {
// Someone killed this Thread, behave as if Timer cancelled
synchronized(queue) {
newTasksMayBeScheduled = false;
queue.clear(); // Eliminate obsolete references
}
}
}
run方法中的mainLoop方法是进行无限循环,检查是否满足条件,如果满足条件,就执行TimerTask实例的run方法。
private void mainLoop() {
while (true) {
try {
TimerTask task;
boolean taskFired;
synchronized(queue) {
// Wait for queue to become non-empty
while (queue.isEmpty() && newTasksMayBeScheduled)
queue.wait();
if (queue.isEmpty())
break; // Queue is empty and will forever remain; die
// Queue nonempty; look at first evt and do the right thing
long currentTime, executionTime;
task = queue.getMin();
synchronized(task.lock) {
if (task.state == TimerTask.CANCELLED) {
queue.removeMin();
continue; // No action required, poll queue again
}
currentTime = System.currentTimeMillis();
executionTime = task.nextExecutionTime;
if (taskFired = (executionTime<=currentTime)) {
if (task.period == 0) { // Non-repeating, remove
queue.removeMin();
task.state = TimerTask.EXECUTED;
} else { // Repeating task, reschedule
queue.rescheduleMin(
task.period<0 ? currentTime - task.period
: executionTime + task.period);
}
}
}
if (!taskFired) // Task hasn't yet fired; wait
queue.wait(executionTime - currentTime);
}
if (taskFired) // Task fired; run it, holding no locks
task.run();
} catch(InterruptedException e) {
}
}
}
schedule方法:
public void schedule(TimerTask task, Date firstTime, long period) {
if (period <= 0)
throw new IllegalArgumentException("Non-positive period.");
sched(task, firstTime.getTime(), -period);
}
在这个方法里将period改成负数传入sched方法。
scheduleAtFixedRate方法:public void scheduleAtFixedRate(TimerTask task, Date firstTime,
long period) {
if (period <= 0)
throw new IllegalArgumentException("Non-positive period.");
sched(task, firstTime.getTime(), period);
}
参数:
* TimerTask task,传入执行体,即满足时间条件就执行的方法,专门有一个抽象类Timetask来管理,需要重写Timetask抽象类里面的run方法进行执行。
* Date firstTime,第一次执行时间,满足这个时间条件,就开始执行;
* long period,执行间隔。
方法体:判断period是否小于等于0,如果小于等于0则抛出"Non-positive period."异常,反之正常则执行sched方法。firTime.getTime()是将Date类型转换为long类型如"1634039142877"、"1634039232120"....,getTime方法是将Date类型转换为long类型,常用于时间的比较时使用。
sched方法:private void sched(TimerTask task, long time, long period) {
if (time < 0)
throw new IllegalArgumentException("Illegal execution time.");
// Constrain value of period sufficiently to prevent numeric
// overflow while still being effectively infinitely large.
if (Math.abs(period) > (Long.MAX_VALUE >> 1))
period >>= 1;
synchronized(queue) {
if (!thread.newTasksMayBeScheduled)
throw new IllegalStateException("Timer already cancelled.");
synchronized(task.lock) {
if (task.state != TimerTask.VIRGIN)
throw new IllegalStateException(
"Task already scheduled or cancelled");
task.nextExecutionTime = time;
task.period = period;
task.state = TimerTask.SCHEDULED;
}
queue.add(task);
if (queue.getMin() == task)
queue.notify();
}
}
参数: 参数还是和在scheduleAtFixedRate方法中基本一样,只不过Date转为long类型。
方法体:逻辑上就是把task加入到队列queue中。
add方法void add(TimerTask task) {
// Grow backing store if necessary
if (size + 1 == queue.length)
queue = Arrays.copyOf(queue, 2*queue.length);
queue[++size] = task;
fixUp(size);
}
其实task就是一个重写了run方法的TimerTask对象,执行重写后的run方法(Runable接口中的方法),
TimerTask类状态:
static final int VIRGIN = 0; //原始状态的
static final int SCHEDULED = 1; //计划的,预定的
static final int EXECUTED = 2; //已执行的
static final int CANCELLED = 3; //已取消的
synchronized():同步代码块,将括号中的对象进行原子化执行
**TimerThread中的run和mainLoop方法**
public void run() {
try {
mainLoop();
} finally {
// Someone killed this Thread, behave as if Timer cancelled
synchronized(queue) {
newTasksMayBeScheduled = false;
queue.clear(); // Eliminate obsolete references
}
}
}



