说明:参考《Java多线程核心技术》
10、Timer定时器
Time类的主要作用是设置计划任务,但封装任务的类却是TimerTask类,执行计划任务的的代码放入TimerTask的子类中。TimerTask是一个抽象类。
1、执行一次某一任务:执行任务的时间晚于当前时间–在未来执行的效果
schedule(TimerTask task, Date time):
public class MyTask extends TimerTask {
@Override
public void run() {
System.out.println("task is ok, time is " + new Date().toString());
}
}
public class MyTaskTest {
public static void main(String[] args) {
System.out.println("current time is " + new Date());
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, 10);
Date runDate = calendar.getTime();
MyTask task = new MyTask();
Timer timer = new Timer();
timer.schedule(task, runDate);
}
}
/**
current time is Wed Jan 09 22:50:36 CST 2019
task is ok, time is Wed Jan 09 22:50:46 CST 2019
*/
Timer源码:
/**Creates a new timer. The associated thread does <i>not</i>
Thread #setDaemon run as a daemon}*/
public Timer() {
this("Timer-" + serialNumber());
}
可见:创建了一个Timer就是启动一个新的线程,那么这个信封线程并不是守护线程,一直在运行。
Timer timer = new Timer(true);
这是一个守护线程,运行完就消失。
2、计划时间早于当前时间–提前运行的效果
// 提前执行
calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) - 10);
TimeTask以队列的方式一个一个被顺序执行的。
源码:
public abstract class TimerTask implements Runnable{
方法schedule(TimerTask task, Date fiertTime, long period):在指定的日期之后按照指定间隔周期,无限循环的执行某一任务。
3、在未来执行:计划时间晚于当前时间
public class MyScheduleTask extends TimerTask{
@Override
public void run() {
System.out.println("task is ok, time is " + new Date());
}
}
public class MyScheduleTest {
public static void main(String[] args) {
System.out.println("currentTime is " + new Date());
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, 10);
Date runDate = calendar.getTime();
System.out.println("schedule time is " + runDate);
MyScheduleTask task = new MyScheduleTask();
Timer timer = new Timer();
timer.schedule(task, runDate, 4000);
}
}
/**
currentTime is Wed Jan 09 23:24:26 CST 2019
schedule time is Wed Jan 09 23:24:36 CST 2019
task is ok, time is Wed Jan 09 23:24:36 CST 2019
task is ok, time is Wed Jan 09 23:24:40 CST 2019
task is ok, time is Wed Jan 09 23:24:44 CST 2019
task is ok, time is Wed Jan 09 23:24:48 CST 2019
...
*/
提前执行: 计划时间早于当前时间:如果计划时间早于当前时间,则立即执行。
// 提前执行
calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) - 10);
schedule源码:
public void schedule(TimerTask task, Date firstTime, long period) {
if (period <= 0)
throw new IllegalArgumentException("Non-positive period.");
sched(task, firstTime.getTime(), -period);
}
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) { //private final TaskQueue queue = new TaskQueue();
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();
}
}
cancel()方法:将自身从任务队列中进行清除,其他任务不受影响:
TimerTask中的cancel源码:
public boolean cancel() {
synchronized(lock) {
boolean result = (state == SCHEDULED);
state = CANCELLED; // 清除当前的任务
return result;
}
}
Timer中的cancel的源码:
public void cancel() {
synchronized(queue) {
thread.newTasksMayBeScheduled = false;
queue.clear();
queue.notify(); // In case queue was already empty.
}
}
void clear() { // 清除所有的任务
// Null out task references to prevent memory leak
for (int i=1; i<=size; i++)
queue[i] = null;
size = 0;
}