1、Timer概述
Timer类我们通常用来执行延迟、定时任务,与其密切相关的类有TimerTask、TaskQueue、TimerThread。与Android的消息机制类似,timer.schedule()不断的将任务扔到TaskQueue中,TimerThread用于不断的循环任务队列执行任务。
人傻话少,裁剪别人写的。
2、任务的执行顺序是否和代码中写的一致?
private void sched(TimerTask task, long time, long period) { if (time < 0) throw new IllegalArgumentException("Illegal execution time."); 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(); } }
当一个任务加到队列中时加了锁,所以多次执行schedule( )代码添加任务,Timer并不能保证任务执行的先后顺序是按照代码中写的顺序。
public class JavaMain { public static void main(String[] args) { Timer timer = new Timer(); timer.schedule(new Task(1), 0); timer.schedule(new Task(2), 0); timer.schedule(new Task(3), 0); timer.schedule(new Task(4), 0); timer.schedule(new Task(5), 0); timer.schedule(new Task(6), 0); timer.schedule(new Task(7), 0); } static class Task extends TimerTask { private int index = 0; Task(int i) { index = i; } @Override public void run() { System.out.println("hell world! = " + index); try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } } } }
执行结果:
hell world! = 1
hell world! = 7
hell world! = 6
hell world! = 5
hell world! = 4
hell world! = 3
hell world! = 2
3、源码分析
// 用于创建任务 public class Timer { private final TaskQueue queue = new TaskQueue(); private final TimerThread thread = new TimerThread(queue); // 以自增形式,标记任务名称 private final static AtomicInteger nextSerialNumber = new AtomicInteger(0); 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(); } /** * 是否守护线程 * * @param name * @param isDaemon */ 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); } /** * 添加任务,原子操作 * * @param task * @param time * @param period */ private void sched(TimerTask task, long time, long period) { if (time < 0) throw new IllegalArgumentException("Illegal execution time."); 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(); } } /** * 将queue所有任务置为null. */ public void cancel() { synchronized (queue) { thread.newTasksMayBeScheduled = false; queue.clear(); queue.notify(); // In case queue was already empty. } } /** * 将所有状态为CANCELLED的任务从queue中移除 * * @return */ 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; } }
// 用于封装一个任务 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(); public boolean cancel() { synchronized (lock) { boolean result = (state == SCHEDULED); state = CANCELLED; return result; } } public long scheduledExecutionTime() { synchronized (lock) { return (period < 0 ? nextExecutionTime + period : nextExecutionTime - period); } } }
// 用于存储任务 public class TaskQueue { /** * 以数组的形式,维护的是一个平衡二叉树 */ private TimerTask[] queue = new TimerTask[128]; private int size = 0; // 没有 queue[0] ,应该是为了方便记忆 int size() { return size; } void add(TimerTask task) { if (size + 1 == queue.length) { queue = Arrays.copyOf(queue, 2 * queue.length); // 扩充为原来的一倍 } queue[++size] = task; fixUp(size); } TimerTask getMin() { return queue[1]; } TimerTask get(int i) { return queue[i]; } /** * 移除并做调整 * 将无用的元素放在最后 */ void removeMin() { queue[1] = queue[size]; queue[size--] = null; fixDown(1); } // 移除并未并做调整 void quickRemove(int i) { assert i <= size; queue[i] = queue[size]; queue[size--] = null; } void rescheduleMin(long newTime) { queue[1].nextExecutionTime = newTime; fixDown(1); } boolean isEmpty() { return size == 0; } void clear() { 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++; 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); } }
// 用于执行未执行任务 public class TimerThread extends Thread { boolean newTasksMayBeScheduled = true; private TaskQueue queue; TimerThread(TaskQueue queue) { this.queue = queue; } public void run() { try { mainLoop(); } finally { synchronized (queue) { newTasksMayBeScheduled = false; queue.clear(); } } } // 核心代码 private void mainLoop() { while (true) { try { TimerTask task; boolean taskFired; synchronized (queue) { /** * 线程启动后并未执行,等待queue.notify(),以免做无用功 */ while (queue.isEmpty() && newTasksMayBeScheduled) queue.wait(); if (queue.isEmpty()) break; // 没有任务了 long currentTime, executionTime; task = queue.getMin(); // 锁定任务,执行期间禁止其他任务执行 synchronized (task.lock) { if (task.state == TimerTask.CANCELLED) { queue.removeMin(); continue; } currentTime = System.currentTimeMillis(); executionTime = task.nextExecutionTime; if (taskFired = (executionTime <= currentTime)) { if (task.period == 0) { // 已经执行过了,至少时间过了 queue.removeMin(); task.state = TimerTask.EXECUTED; } else { // 重回队列,重复执行 queue.rescheduleMin( task.period < 0 ? currentTime - task.period : executionTime + task.period); } } } if (!taskFired) { queue.wait(executionTime - currentTime); } } if (taskFired) { task.run(); } } catch (InterruptedException e) { } } } }
cancle与purge区别
/** * 清空任务队列 */ public void cancel() { synchronized(queue) { thread.newTasksMayBeScheduled = false; queue.clear(); queue.notify(); // In case queue was already empty. } }
/** * 将所有标志位CANCELLED状态的任务移除掉 */ 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; }