java.util.Timer是比较底层的一个java定时任务执行类,其底层也是基于java.util.Thread
Timer是一个总的类,里面成员变量包含了java.util.TaskQueue,java.util.TimerThread
其中TaskQueue封装了一个TimerTask的数组(优先队列)。TimerTask对应每个任务。其数组为优先队列,先执行的任务放在前面。
java.util.Timer#Timer(java.lang.String)构造函数和成员变量
/**
* The timer task queue. This data structure is shared with the timer
* thread. The timer produces tasks, via its various schedule calls,
* and the timer thread consumes, executing timer tasks as appropriate,
* and removing them from the queue when they're obsolete.
*/
private final TaskQueue queue = new TaskQueue();
/**
* The timer thread.
*/
private final TimerThread thread = new TimerThread(queue);
......
/**
* Creates a new timer whose associated thread has the specified name.
* The associated thread does <i>not</i>
* {@linkplain Thread#setDaemon run as a daemon}.
*
* @param name the name of the associated thread
* @throws NullPointerException if {@code name} is null
* @since 1.5
*/
public Timer(String name) {
thread.setName(name);
thread.start();
}
可见,Timer主要由TimerThread这个线程实现多个任务。
java.util.Timer#sched 将任务加入到优先队列中
进入java.util.Timer#schedule(java.util.TimerTask, long, long)再进入java.util.Timer#sched
/**
* Schedule the specified timer task for execution at the specified
* time with the specified period, in milliseconds. If period is
* positive, the task is scheduled for repeated execution; if period is
* zero, the task is scheduled for one-time execution. Time is specified
* in Date.getTime() format. This method checks timer state, task state,
* and initial execution time, but not period.
*
* @throws IllegalArgumentException if <tt>time</tt> is negative.
* @throws IllegalStateException if task was already scheduled or
* cancelled, timer was cancelled, or timer thread terminated.
* @throws NullPointerException if {@code task} is null
*/
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();
}
}
注意最后2行,要唤醒有queue锁的线程,因为当优先队列没有元素时,线程会wait以节约资源。
java.util.TimerThread#mainLoop是执行任务的主要方法
进入java.util.TimerThread#run再进入java.util.TimerThread#mainLoop
/**
* The main timer loop. (See class comment.)
*/
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) {
}
}
}
该方法主要获得一个最近执行的任务,先判断该任务的类型。当该任务是执行一次,则从优先队列中删除,否则更新下一次执行时间,更新优先队列。该任务队列是阻塞的。当任务队列无数据时,挂起TimerThread线程,或者判断下一个任务执行时间挂起executionTime - currentTime秒。
当任务执行完后,该循环并不会退出,需要把上面循环中判断的newTasksMayBeScheduled置为false,所以退出线程需要执行java.util.Timer#cancel方法。
/**
* Terminates this timer, discarding any currently scheduled tasks.
* Does not interfere with a currently executing task (if it exists).
* Once a timer has been terminated, its execution thread terminates
* gracefully, and no more tasks may be scheduled on it.
*
* <p>Note that calling this method from within the run method of a
* timer task that was invoked by this timer absolutely guarantees that
* the ongoing task execution is the last task execution that will ever
* be performed by this timer.
*
* <p>This method may be called repeatedly; the second and subsequent
* calls have no effect.
*/
public void cancel() {
synchronized(queue) {
thread.newTasksMayBeScheduled = false;
queue.clear();
queue.notify(); // In case queue was already empty.
}
}
总结:
1.当目前没有任务执行时,调用wait()方法挂起线程以节约资源。
2.优先队列维护最近执行的任务