java之 Timer 类的使用以及深入理解
根据是否循环执行分为两类: //只执行一次 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 源码:
程序运行:
在初始化Timer时 ,开启一个线程循环提取任务数组中的任务,如果任务数组为空,线程等待直到添加任务;
当添加任务时,唤醒线程,提取数组中标记为1的任务,
如果该任务状态为CANCELLED,则从数组中删除任务,continue ,继续循环提取任务;
然后将当前时间与任务执行时间点比较 标记taskFired=executionTime<=currentTime;
taskFired =false ,说明任务执行时间还没到,则调用wait等待(executionTime-currentTime) 时间长度,然后循环重新提取该任务;
taskFired =true,说明任务执行时间已经到了,或者过去了。继续判断 任务循环时间间隔period;
period=0时,说明此次任务是非循环任务,直接将该任务从数组中删除,并将状态置为EXECUTED,然后执行任务的run方法!
period!=0时,说明此次任务时循环任务,将该任务的执行时间点向前推进,具体推进时间根据调用的方法判断;
如果是schedule方法,则在当前时间基础上向前推进period时间长度;
如果是scheduleAtFixedRate方法,则在当前任务执行时间点基础上向前推进period时间长度,
最后执行任务的run方法;循环提取任务
package java.util; import java.util.Date; import java.util.concurrent.atomic.AtomicInteger; public class Timer { private final TaskQueue queue = new TaskQueue(); 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. } } }; 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(); } //在初始化Timer时,确定线程名称,以及是否是守护线程 ,开启线程 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) { 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(); } } public void cancel() { synchronized(queue) { thread.newTasksMayBeScheduled = false; queue.clear(); queue.notify(); // In case queue was already empty. } } //净化,清除timer中标记为CANCELLED的TIMETASK, 返回值为清除个数 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; } } //自定义线程 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 } } } 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; } currentTime = System.currentTimeMillis(); executionTime = task.nextExecutionTime; if (taskFired = (executionTime<=currentTime)) { if (task.period == 0) { // 循环条件为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) { } } } } /** * * 任务管理内部类 */ class TaskQueue { //初始化 128个空间,实际使用127个 位置编号为0的位置不使用 private TimerTask[] queue = new TimerTask[128]; private int size = 0; int size() { return size; } //添加任务,如果空间不足,空间*2,,然后排序(将nextExecutionTime最小的排到1位置) 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); } //得到最小的nextExecutionTime的任务 TimerTask getMin() { return queue[1]; } //得到指定位置的任务 TimerTask get(int i) { return queue[i]; } //删除最小nextExecutionTime的任务,排序(将nextExecutionTime最小的排到1位置) void removeMin() { queue[1] = queue[size]; queue[size--] = null; // Drop extra reference to prevent memory leak fixDown(1); } //快速删除指定位置的任务 void quickRemove(int i) { assert i <= size; queue[i] = queue[size]; queue[size--] = null; // Drop extra ref to prevent memory leak } //重新设置最小nextExecutionTime的任务的nextExecutionTime,排序(将nextExecutionTime最小的排到1位置) void rescheduleMin(long newTime) { queue[1].nextExecutionTime = newTime; fixDown(1); } //数组是否为空 boolean isEmpty() { return size==0; } //清空数组 void clear() { // Null out task references to prevent memory leak for (int i=1; i<=size; i++) queue[i] = null; size = 0; } //将nextExecutionTime最小的排到1位置 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; } } //将nextExecutionTime最小的排到1位置 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; } } //排序(将nextExecutionTime最小的排到1位置) 在快速删除任务后调用 void heapify() { for (int i = size/2; i >= 1; i--) fixDown(i); } }
TimerTask源码:
功能:用户任务,Timer执行任务实体(任务状态,任务下次执行时间点,任务循环时间间隔,任务本体【run】)
package java.util; /** * 虽然实现了Runnable接口 但是在Timer中直接调用run方法, * */ 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();//自定义任务 //退出 任务执行完毕后,退出返回 true ,未执行完 就退出 返回false 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); } } }
原文:https://www.cnblogs.com/xiaotaoqi/p/6874713.html#a
浙公网安备 33010602011771号