美文网首页技术干货Java 杂谈
关于Timer你要知道的

关于Timer你要知道的

作者: 尔乐 | 来源:发表于2017-08-28 11:51 被阅读20次

写在前面:Timer使用一个队列缓存要执行的任务,可以加入多个TimerTask,在一个独立线程中顺序执行任务。

首先看看Timer的成员和内部方法:
schedule(TimerTask task,long delay)

首先包含多个schedule的多态方法。
Timer 构造方法的多态
持有一个TimerQueue 的队列,也就是前面所说的用于缓存待执行任务的队列。
持有一个TimerThread的变量,就是前面说的工作线程。
结构,内容都比较简单,下面慢慢来分析。
有一个队列,那么大胆猜测,是可以执行多个TimerTask,有一个线程,那么同时猜测,是在单独线程去执行Timer。
下面看一下,工作线程TimerThread这个类的实现。

Class TimerThread extends Thread {
    private TimerQueue queue;
    TimerThread(TimerQueue queue){
        this.queue= queue;
    }
       public void run(){
        try{
            mainLoop();//关键方法。
            }finally{
                …
            }
    }
}

下面看一下 mainloop()的实现 。

 /**
     * The main timer loop.  (See class comment.)
     */
    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
                                          //如果时间还没到,那么等待剩余时长。
                        queue.wait(executionTime - currentTime);
                }
                if (taskFired)  // Task fired; run it, holding no locks
                                      //时间到了或者时间已经过了,那么立刻执行。
                    task.run();//同步执行,如果这里执行时间过长,就会影响到后续的执行时间。
            } catch(InterruptedException e) {
            }
        }
    }
综上:使用Timer会因为上一个任务(或者同一个任务的上一个周期)执行时间超过间隔时间,使得后一个任务(或者后一个周期)的run的开始时间延后,也就是timer 会照成时间间隔不准的问题。

相关文章

网友评论

    本文标题:关于Timer你要知道的

    本文链接:https://www.haomeiwen.com/subject/dtnwdxtx.html