Timer的源码分析

来源:互联网 发布:软件开发工程师是什么 编辑:程序博客网 时间:2024/05/17 04:04

         这段时间用到了Timer做一个定时任务,因为业务的原因就需要调计算机的时间,发现一个问题把时间先调大于当前时间在调回来发现timer就没有执行了,感觉Timer不会这么坑吧,所以就看了一下源码。下面就把我理解Timer的分享一下

       先看Timer类的结构里面内置二个重要的组件TimerThread(定时线程)和TaskQueue(任务队列)下面是Timer的部分源码


  我们现在分析类TimerThread


TimerThread是Thread的子类,里面内置TaskQueue对象,实现Runnable接口的run方法

在看看mainLoop方法



上面的方法告诉我们只要TaskQueue里面为空并且newTasksMayBeScheduled为true的话,这个线程一直处于等待状态。如果队列为空newTasksMayBeScheduled为false时候该线程就直接跑完了,其他情况的话先从任务队列里面取出下标为1的元素,计算一下当前时间和下个周期执行时间那个大,然后当前时间大于或等于下个一个周期执行时间

话,先计算个下下个执行周期时间然后跟新任务队列,并执行这个任务,否则直接等待(executionTime-currentTime)这个周期。然后在循环上面操作(读到这里当时我有个疑问是为什么下标为1的任务为什么是最近要执行的job,其实这个与TaskQueue这个类添加元素有关,下面会分析这个类)

      TaskQueue类里面有个TimerTask数组queue,核心方法有add(TimerTask task),getMin(),rescheduleMin(long newTime),fixUp(int k),fixDown(int k)下面我们一一分析



上图是fixDown和fixUp的源码。其实这里保证了当添加一个元素的时候和修改一个元素的下个执行周期的时候所有的子节点都大于或等于父节点


这个方法会在TimerThread中的mainLoop方法里被调用,当取出的任务的下一个执行时间大于等于当前时间的话会调用这个方法,因为在执行task的同时,需要修改计算这个任务的下个周期执行时间,并放到队列里面并要维护TaskQueue的特性(子节点的下个执行周期一定要大于父节点的执行周期)。这样保证getMin的时候取到的下个执行周期是最近的。


getMin的源码

现在介绍这二个主要的类,我们在看Timer类

我们




当我们添加一个TimerTask的时候会调用上面方法,加到TaskQueue队列中,与TimerThread的mainLoop不断重复处理



      在Timer的开发中在编码自己的TimerTask任务的时候注意要处理自己的异常,从上面的源码的可以知道他是一个主线程中循环处理queue里面的任务的,然后在执行的你的代码抛出异常的时候会导致整个定时任务崩溃不能正常工作

原创粉丝点击