您的位置:首页 > 编程语言 > Java开发

Java定时器之Timer源码剖析

2017-08-23 00:00 417 查看
Timer类中有两个主要的引用:

TaskQueue:任务队列

TimerThread:真正执行任务的线程

Timer:任务定时的调度

一、TaskQueue:任务队列

采用数组实现队列:



将元素添加到队列,调整堆。其实是一个堆。



这个TaskQueue是根据nextExecutionTime下一次执行的时间排序的。(调整堆)



什么是堆?像如下的方式,如果不懂的话,自己百度。



注意:TaskQueue这个类很简单,就是一个任务队列,按下一个任务执行的时间建立的一个堆。

二、TimerThread:具体执行任务的线程

TimerThread是继承Thread类,然后再run方法中调用mainLoop(),下面就介绍TimerThread类。



TimerThread线程启动之后,就是一直死循环去获取队列的任务





注意:上面在判断到达执行任务的时间之后,再判断是否要重复执行,如果要重复执行的话,重新计算了两个任务的时间间隔:

代码:

task.period<0 ? currentTime - task.period : executionTime + task.period

分析:

period<0代表是上一个任务执行的时间长,超过了设置的前面设置的时间,

下面举个例子:

任务A --9s--- 任务B --9s-- 任务C (注意:9s是我们的设置的任务执行间隔时间)。

但是执行了10s的话,下一个任务相当于延迟了1s,那就currentTime - task.period设置延迟的时间执行。否则正常执行(executionTime + task.period)。



三、Timer:任务的调度器

创建Timer对象,就启动了TimerThread线程。



任务规划器:

这里的执行的线程是具体的你代码中哪个线程调用的schedule方法。在我写的代码里由于我是在main方法中直接写的话,这里的是主线程中执行的。





下面是我看完源码之后的理解:

1、一个Timer可以看做一个线程在调度任务。这样有一定的缺点是下一个任务必须等待下一个任务的执行。可以看做任务的串行执行。也就是可以看做同步。如果要是任务执行的时间与设置的时间间隔不冲突的话,这个不是问题。

2、TimerThread线程循环的在干活,不会退出。必须我们手动调用timer.cancel()方法才会退出。这就涉及到了TimerThread与其它线程通信的问题了,比如主线程,也是它的父线程。一般此时的可能退出了,这样的话,没有线程跟TimerThread通信,那它就会成功一个无用的线程。类似于Linux中的“僵尸进程”,线程资源没办法回收。就算它的父线程不退出的话,也办法释放线程资源,因为TimerThread完全封装到了Timer里面,它干完了活没办法通知父线程,父线程自然不会调用timer.cancel()。

Timer#cancel代码如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java