今天修复了一个定时任务,看了点源码,记录一下。 主要是Timer的6个方法的分析,首先先看一下这6个方法都调用的方法sched:oop
private void sched(TimerTask task, long time, long period) { if (time < 0) throw new IllegalArgumentException("Illegal execution time."); 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(); } }
当调用sched方法时, 1.period周期为正,则任务被安排为重复执行;若是周期为零,则任务被安排为一次性执行;ui
2.当time时间为过去时间时,若是period周期为正,则按照‘过去时间time+period周期’执行;若是周期为负, 按照 ‘当前时间+period周期’执行,即执行当前时间之后的任务。code
能够参考源码以下:rem
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 //这里判断period,为正返回executionTime + task.period //为负返回currentTime - task.period 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) { } } } }
明白了上面的原理,接下来就比较容易理解6个方法了。get
public void schedule(TimerTask task, long delay) { if (delay < 0) throw new IllegalArgumentException("Negative delay."); sched(task, System.currentTimeMillis()+delay, 0); }
sched、mainLoop方法源码能够看出:源码
public void schedule(TimerTask task, Date time) { sched(task, time.getTime(), 0); }
sched、mainLoop方法源码能够看出:it
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); }
sched、mainLoop方法源码能够看出:io
public void schedule(TimerTask task, Date firstTime, long period) { if (period <= 0) throw new IllegalArgumentException("Non-positive period."); sched(task, firstTime.getTime(), -period); }
sched、mainLoop方法源码能够看出:thread
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); }
sched、mainLoop方法源码能够看出:require
public void scheduleAtFixedRate(TimerTask task, Date firstTime, long period) { if (period <= 0) throw new IllegalArgumentException("Non-positive period."); sched(task, firstTime.getTime(), period); }
sched、mainLoop方法源码能够看出: