根据是否循环执行分为两类:
//只执行一次
public void schedule(TimerTask task, long delay);
public void schedule(TimerTask task, Date time);
//循环执行
//在循环执行类别中根据循环时间间隔又可以分为两类
public void schedule(TimerTask task, long delay, long period) ;
public void schedule(TimerTask task, Date firstTime, long period) ;
public void scheduleAtFixedRate(TimerTask task, long delay, long period)
public void scheduleAtFixedRate(TimerTask task, Date firstTime, long period)
只执行一次
Timer timer = new Timer();
//延迟1000ms执行程序
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("IMP 当前时间" + this.scheduledExecutionTime());
}
}, 1000);
//延迟10000ms执行程序
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("IMP 当前时间" + this.scheduledExecutionTime());
}
}, new Date(System.currentTimeMillis() + 10000));
循环执行
Timer timer = new Timer();
//前一次执行程序结束后 2000ms 后开始执行下一次程序
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("IMP 当前时间" + this.scheduledExecutionTime());
}
}, 0,2000);
//前一次程序执行开始 后 2000ms后开始执行下一次程序
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println("IMP 当前时间" + this.scheduledExecutionTime());
}
},0,2000);
源码分析
Timer
public class Timer {
//维护TaskQueue
private final TaskQueue queue = new TaskQueue();
//维护TimerThread
private final TimerThread thread = new TimerThread(queue);
private final Object threadReaper = new Object() {
protected void finalize() throws Throwable {
synchronized(queue) {
thread.newTasksMayBeScheduled = false;
queue.notify(); // In case queue is empty.
}
}
};
//使用原子操作类来保证count的准确性
private final static AtomicInteger nextSerialNumber = new AtomicInteger(0);
//getAndIncrement的实现方式,不断的调用compareAndSwapInt方法
//返回的是旧值
private static int serialNumber() {
return nextSerialNumber.getAndIncrement();
}
public Timer() {
this("Timer-" + serialNumber());
}
public Timer(boolean isDaemon) {
this("Timer-" + serialNumber(), isDaemon);
}
public Timer(String name) {
thread.setName(name);
thread.start();
}
//根据传入的参数,决定是否设置守护进程
public Timer(String name, boolean isDaemon) {
thread.setName(name);
thread.setDaemon(isDaemon);
thread.start();
}
public void schedule(TimerTask task, long delay) {
if (delay < 0)
throw new IllegalArgumentException("Negative delay.");
sched(task, System.currentTimeMillis()+delay, 0);
}
public void schedule(TimerTask task, Date time) {
sched(task, time.getTime(), 0);
}
public void schedule(TimerTask task, long delay, long period) {
if (delay < 0)
throw new IllegalArgumentException("Negative delay.");
if (period <= 0)
throw new IllegalArgumentException("Non-positive period.");
sched(task, System.currentTimeMillis()+delay, -period);
}
public void schedule(TimerTask task, Date firstTime, long period) {
if (period <= 0)
throw new IllegalArgumentException("Non-positive period.");
sched(task, firstTime.getTime(), -period);
}
public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
if (delay < 0)
throw new IllegalArgumentException("Negative delay.");
if (period <= 0)
throw new IllegalArgumentException("Non-positive period.");
sched(task, System.currentTimeMillis()+delay, period);
}
public void scheduleAtFixedRate(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) {
if (!thread.newTasksMayBeScheduled)
throw new IllegalStateException("Timer already cancelled.");
synchronized(task.lock) {
//如果当前TimerTask的状态不等于VIRGIN,那么抛出异常
if (task.state != TimerTask.VIRGIN)
throw new IllegalStateException(
"Task already scheduled or cancelled");
task.nextExecutionTime = time;
task.period = period;
task.state = TimerTask.SCHEDULED;
}
//将TimerTask添加至TaskQueue
queue.add(task);
if (queue.getMin() == task)
queue.notify();
}
}
//取消Timer,reset状态,且清除queue
public void cancel() {
synchronized(queue) {
thread.newTasksMayBeScheduled = false;
queue.clear();
queue.notify(); // In case queue was already empty.
}
}
//从TaskQueue中移除掉所有已经取消的TimerTask,这个方法不会对Timer的行为造成影响,但是从队列中删除对已取消任务的引用。大多数的项目中都不需要调用此方法,它是为少数几个取消大量任务的应用程序而设计的。
public int purge() {
int result = 0;
synchronized(queue) {
for (int i = queue.size(); i > 0; i--) {
if (queue.get(i).state == TimerTask.CANCELLED) {
queue.quickRemove(i);
result++;
}
}
if (result != 0)
queue.heapify();
}
return result;
}
}
TimerThread
/**
* This "helper class" implements the timer's task execution thread, which
* waits for tasks on the timer queue, executions them when they fire,
* reschedules repeating tasks, and removes cancelled tasks and spent
* non-repeating tasks from the queue.
*/
class TimerThread extends Thread {
boolean newTasksMayBeScheduled = true;
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
}
}
}
//死循环,不断的取TimerTask
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())
// Queue is empty and will forever remain; die
break;
// 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) {
}
}
}
}
TaskQueue
class TaskQueue {
//维护一个长度为128的TimerTask数组
private TimerTask[] queue = new TimerTask[128];
private int size = 0;
int size() {
return size;
}
//添加TimerTask到queue中
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);
}
//获取最小index的TimerTask
TimerTask getMin() {
return queue[1];
}
//根据index返回对应的TimerTask
TimerTask get(int i) {
return queue[i];
}
//移除掉最小的TimerTask
void removeMin() {
queue[1] = queue[size];
queue[size--] = null; // Drop extra reference to prevent memory leak
fixDown(1);
}
//快速移除指定Index的TimerTask
void quickRemove(int i) {
assert i <= size;
queue[i] = queue[size];
queue[size--] = null; // Drop extra ref to prevent memory leak
}
//重新制定执行时间
void rescheduleMin(long newTime) {
queue[1].nextExecutionTime = newTime;
fixDown(1);
}
//判断当前数组的大小
boolean isEmpty() {
return size==0;
}
//清除所有的TimerTask
void clear() {
// Null out task references to prevent memory leak
for (int i=1; i<=size; i++)
queue[i] = null;
size = 0;
}
private void fixUp(int k) {
while (k > 1) {
int j = k >> 1;
if (queue[j].nextExecutionTime <= queue[k].nextExecutionTime)
break;
TimerTask tmp = queue[j]; queue[j] = queue[k]; queue[k] = tmp;
k = j;
}
}
private void fixDown(int k) {
int j;
while ((j = k << 1) <= size && j > 0) {
if (j < size &&
queue[j].nextExecutionTime > queue[j+1].nextExecutionTime)
j++; // j indexes smallest kid
if (queue[k].nextExecutionTime <= queue[j].nextExecutionTime)
break;
TimerTask tmp = queue[j]; queue[j] = queue[k]; queue[k] = tmp;
k = j;
}
}
//堆化
void heapify() {
for (int i = size/2; i >= 1; i--)
fixDown(i);
}
}
TimerTask
public abstract class TimerTask implements Runnable {
final Object lock = new Object();
int state = VIRGIN;
//原始状态的
static final int VIRGIN = 0;
//已排程的
static final int SCHEDULED = 1;
//执行中的
static final int EXECUTED = 2;
//取消的
static final int CANCELLED = 3;
//下一次执行时间
long nextExecutionTime;
long period = 0;
protected TimerTask() {
}
public abstract void run();
//修改TimerTask的状态
public boolean cancel() {
synchronized(lock) {
boolean result = (state == SCHEDULED);
state = CANCELLED;
return result;
}
}
//如果period小于0,那么返回下一次执行时间+周期
//如果period大于0,那么返回下一次执行时间-周期
public long scheduledExecutionTime() {
synchronized(lock) {
return (period < 0 ? nextExecutionTime + period
: nextExecutionTime - period);
}
}
}
Timer执行流程:
- 当Timer被创建成功之后,唯一一个线程TimerThread将开始执行
- 不断的从TimerQueue中获取TimerTask
- 判断TimerTask的状态、时间,如果时间被用完,那么移除TimerTask,否则调用TimerTask的run方法
- 当TimerTask需要取消时,可以调用TimerTask的cancel方法
- 当Timer需要取消时,调用Timer.cancel方法
总结:
- TimerTask 只能被schedule一次,然后被cancel后,就不能再被schedule调用,否则会抛异常。java.lang.IllegalStateException: TimerTask is canceled.
- 需要反复注册任务的话,只能重建TimerTask.
- TimerThread的TimerTask是存在执行顺序的.
- Timer不保证任务执行的十分精确,schedule函数尽量让每一次间隔精准,而scheduleAtFixedRate则是,尽量在算好的时间执行.
- TimerThread的是线程安全的.
有任何问题,欢迎指出
网友评论