定时器功能定义
- 能够延迟执行任务
- 能够周期性执行某个任务
- 能够添加多个任务,按照任务执行时间依次执行
单个任务如何延迟执行?
执行线程需要一直运行,等待任务时间到了再执行。
所以需要一个死循环,让线程一直运行下去。
但是没有任务时,死循环会空转CPU,所以需要释放CPU。
如何让线程释放CPU,又让线程不死进行等待?
sleep()或wait(),把CPU交出去。
线程应该等待多久?
sleep()或wait()都可以传递要等待多长时间,等待时长可以用任务时间减去当前时间计算而来。
如何周期性执行一个任务?
任务执行完后,计算新的等待时间,继续让线程等待。
多个任务如何处理任务优先级?
每个任务都要有一个执行时间,按任务执行时间从小到大排序,先执行时间小的任务。
怎么排序?
观察任务添加的特点。
任务可能会动态添加,比如Android中的Handler,消息队列可以随时插入新的消息,并且消息的执行时间完全任意。
这就需要在线排序算法,用优先队列,创建最小堆,往堆中添加一个元素,调整堆只需要O(log n)的时间复杂度。
如果使用离线的基于比较的排序算法,时间复杂度O(n * log n),插入排序时间最短,最多花费O(n),但是都没调整堆时间少。
任务排序好后怎么依次执行?
读取时间最小的任务,把它的执行时间减去当前时间,得到等待时间,让线程sleep或wait这个时间。
等到线程唤醒后,执行任务,从队列中移除这个已执行的任务,取下一个任务,再计算等待时间。
后续任务重复这个流程。
线程在等待执行了,新任务想插队先执行怎么处理?
新任务添加到优先队列后,立刻唤醒执行线程,重新计算要等待的时间,保证执行线程始终等待执行时间最小的时间的任务。
单个任务执行时间过长,导致后面任务没有按时执行怎么办?
开启多个执行线程,多线程从同一个任务队列中取任务,队列中的任务按时间排序好。
相当于设计一个带延迟功能的线程池了,即ScheduledThreadPoolExecutor。