定时执行Timer的源码阅读
Timer的实现原理:
?
1:timer简介;
?
定制执行一个task,谁用谁知道;
?
2:timer使用
?
?
Timer instance = new Timer(true);instance .schedule( new TimerTask() { public void run() { //do something } } }, TimeUnit.NANOSECONDS.toMillis(expirationNanos));??
?
?
3:timerThread
?
timer实现定时主要是靠内部的一个TimerThread无线循环来执行对应的task;
?
TimerThread有一个mainloop;
?
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 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //这个地方是如果执行的task还没到时间就进入等待; queue.wait(executionTime - currentTime); } if (taskFired) // Task fired; run it, holding no locks task.run(); } catch(InterruptedException e) { } } }??
等待主要是靠wait(timeout)来做的;
?
?
?
4:timerQueue
?
对task的管理主要是靠内部的TaskQueue来进行操作的;这个其实是一个有序的queue数据结构;
最上面的就是最近需要进行执行的超时任务,每次都把第一个搞出来进行判断执行,来完成对多任务的组合定时;
就是这个思路;
?
可以看到这个queue每次添加之后都会进行一次排序;
?
/** * Adds a new task to the priority 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); }??
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; } }??
?
ok,简单到这里,终于圆了我看源码的欲望;
?