内部构成说明
Timer
定时器,其维护了一个异步线程TimerThread
和一个优先队列TaskQueue
,异步线程的作用就是取出任务执行,然后如果是轮训任务,在执行完之后再将其放回队列。
TimerTask
抽象类,继承了Runnable
接口,表示单个任务对象,需要使用者实现任务内容。
队列的有序性保证
队列采用数组表示堆结构来保证整体有序性,堆结构的特点是平衡二叉树,任意节点(N)都小于其两个子节点(子节点分别为2N和2N+1),根据这个特性,队列增加或删除元素的方式如下:
-
增加元素
直接在数组后面增加元素,如果超过
size
(默认128)则扩容,增加元素后,不断和父元素比较上移,直到保持整个堆的有序性 -
删除元素
当堆顶被取走后,queue[1]需要被删除,那么将队尾元素queue[size]替换到堆顶,然后不断与其两个子节点中较小的进行交换位置,也就是说不断下沉到堆底。
如何调度任务
队列有两个释放锁的条件:
- 当队列为空时,将调用
queue.wait()
方法来等待队列进入任务后通过queue.notify()
唤醒 - 当队列执行任务后,查询最近执行任务的间隔时间,比如:最近一个任务还差50ms将被执行,那么调用
queue.wait(50)
来进行等待
Timer的问题
Timer内部仅有一个线程来进行任务调度,当某一任务执行缓慢时,该任务不断循环执行、放回队列、再次被执行,那么将造成其他任务的饥饿问题。
所以更推荐使用ScheduledExecutorService
,后者内部使用线程池来执行任务,且对于任务到期判定使用相对时间而不是绝对时间,对系统时间不如Timer
敏感。