从Timer中学习优先队列的实现
从Timer中学习优先队列的实现
Timer是Java定时器的实现,用来调度定时执行的任务和执行一次的任务,就像JavaScript的setInterval
和setTimeout
的意思,它也可以作为后台程序(Daemon)运行。
Timer
Timer调度的实现是通过TimerThread辅助类来实现的,在构造Timer实例的时候TimerThread就开始运行了;TimerThread需要从队列(TaskQueue)中获得需要被执行的任务(TimerTask),这是一个优先队列,TimeTask的executionTime(TimerTask设置要执行的时间Date.getTime()形式表示的)越小的越优先执行。
TimerThread如何调度
略
TaskQueue data structure
TaskQueue实现了优先队列的数据结构,内部是一个数组,数组内容实际上是从下标1开始填充的;它其实是用balanced binary heap
来表示的,设父节点是queue[n]
,则它的两个字节点分别是queue[2*n]
和queue[2*n+1]
这个数据结构的API方法包括:
- add(T object)
- getMin()
- removeMin()
- fixDown(int k)
- fixUp(int k)
- heapify()
最重要的两个是fixDown
和fixUp
,表示从queue[k]
节点位置开始demoting
或promoting
。
TaskQueue.fixDown
假设要操作的节点是queue[k]
,那么它的子节点分别是queue[j]
和queue[j+1]
,j=k*2
,对queue[k]
做demoting
处理,
private void fixDown(int k) {int j;while ((j = k << 1) <= size && j > 0) {if (j < size &&queue[j].nextExecutionTime > queue[j+1].nextExecutionTime)j++; // j indexes smallest kidif (queue[k].nextExecutionTime <= queue[j].nextExecutionTime)break;TimerTask tmp = queue[j]; queue[j] = queue[k]; queue[k] = tmp;k = j;}}
1.首先比较两个子节点选出executionTime更小的那个,
2.如果右子节点的executionTime更小,则j++
自增,这样就相当于选择了右节点(下次fixDown的位置从这里开始)
3.然后父节点和选中的更小executionTime子节点比较
4.如果父节点的executionTime更小,则交换父节点和这个子节点
那么为什么要执行2呢
之前,
之后,
如果是queue[j]
变成了父节点就会破坏queue[n]<=queue[2*n+1]
的关系。
然后就是一直fixDown到最后一个节点queue[size]
。
我们可以思考下这个方法的时间复杂度是不是O(logn)
。
TaskQueue.fixUp
假设要操作的节点是queue[k]
,那么它的父节点分别是queue[j]
,j=k/2
,对queue[k]
做promoting
处理,
private void fixUp(int k) {while (k > 1) {int j = k >> 1;if (queue[j].nextExecutionTime <= queue[k].nextExecutionTime)break;TimerTask tmp = queue[j]; queue[j] = queue[k]; queue[k] = tmp;k = j;}}
promoting
比demoting
简单一点,只需要比较queue[k]
和queue[j]
两个节点,然后做交换即可。
TaskQueue other methods
通过fixUp
和fixDown
的方法可以保证整个优先队列的关系,保证queue[1]
的executionTime是最小的。
1.heapify()作用是构建堆,可以从{0,q[1],q[2],...,q[size]}
的数组构建堆,来表示优先队列。
void heapify() {for (int i = size/2; i >= 1; i--)fixDown(i);}
从中间下标到1做fixDown。
2.add(T object),往数组中添加元素,重新构建堆
void add(TimerTask task) {// Grow backing store if necessaryif (size + 1 == queue.length)queue = Arrays.copyOf(queue, 2*queue.length);queue[++size] = task;fixUp(size);}
不过需要判断数组空间是否有剩余,没有则扩展数组,并拷贝原来的数组元素,最后对queue[size]
节点,也是新元素做fixUp。
3.getMin() 直接获得queue[1]
元素
4.removeMin() 将queue[size]
节点替换queue[1]
,然后对queue[1]
做fixDown。
总结
这个TaskQueue的优先队列的实现代码是比较清晰的,重要方法的时间复杂度也可以算优秀。
阅读完这部分代码后或许可以进一步阅读PriorityQueue
。
附:测试代码
从Timer中学习优先队列的实现相关推荐
- 从 bug 中学习:六大开源项目告诉你 go 并发编程的那些坑
作者:richardyao,腾讯 CSIG 后台开发工程师 并发编程中,go 不仅仅支持传统的通过共享内存的方式来通信,更推崇通过channel来传递消息,这种新的并发编程模型会出现不同于以往的bug ...
- 随想录(在实践中学习kernel代码)
[声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 记得我在读书的时候,虽然老师也教过操作系统的课程,但是自己的理解却不是很充分,实践部分的内容就更 ...
- 《从案例中学习JavaScript》之实现对话效果
今天突发奇想,js能不能通过字符串和定时器来实现游戏中的对话效果呢.试了一下,还真挺好玩的. 上效果图: 本节涉及的知识点: 字符串的charAt方法 js定时器setInterval(轮询) ### ...
- linux服务器中学习使用FFmpeg命令overlay滤镜用法
linux服务器中学习使用FFmpeg命令overlay滤镜用法 1.overlay技术简介 2.命令行用法 2.1 视频中叠加图标 2.1.1 直接叠加图标 2.1.2 延时叠加图标 2.2 视频中 ...
- 我们从工程项目中学习什么?
这个题目有点大,我在此仅限于技术层面. 这篇文章呢很早就想写,真正促使我付诸行动的是大约两个月前我开始给Mimas team讲街机模拟器的设计,大家普遍很漠然,大概完全搞不懂我为什么要讲这种东东 ...
- 浙大吴飞教授:尽管AlphaGo Zero已强大到从经验中学习模型,我也绝不赞同马斯克和霍金的威胁论,人才是智能的最终主宰
记者 | 鸽子 在整个采访过程中,吴飞教授在回答中给人的最大感受是温和.儒雅.他没有激烈的言辞,也没有犀利的观点,不会一开始直接抛出自己的判断,而是将所有的提问,看作是一次学术上的严谨探讨,从问题本身 ...
- 《从缺陷中学习C/C++》——6.15 试图产生的指针很可能不存在
本节书摘来自异步社区出版社<从缺陷中学习C/C++>一书中的第6章,第6.15节,作者: 刘新浙 , 刘玲 , 王超 , 李敬娜 , ,更多章节内容可以访问云栖社区"异步社区&q ...
- rust墙壁升级点什么_分享:如何在阅读Rust项目源码中学习
今天做了一个Substrate相关的小分享,公开出来. 因为我平时也比较忙,昨天才选定了本次分享的主题,准备比较仓促,细节可能不是很充足,但分享的目的也是给大家提供一个学习的思路,更多的细节大家可以在 ...
- 极客新闻——05、如何在工作中学习和成长?
本文笔记全部来自<极客新闻>--新鲜的技术资讯.权威的趋势剖析.别样的技术洞察 关于如何进行自我学习的话题? 不同的人可能有不同的回答,总结起来就是阅读博客.参加技术大会.读书.利用闲暇时 ...
- 3D U-Net:从稀疏注释中学习密集的体积分割
作者:Tom Hardy Date:2020-01-10 来源:3D U-Net:从稀疏注释中学习密集的体积分割
最新文章
- java 服务器发布_我如何在java中发布到服务器?
- ldap集成nginx
- Vue002_计算属性和监视
- 数字和为sum的方法数-01背包计数问题
- 判断请求来自手机还是PC
- java的et5_Javascript与java相同的3des加密(使用etdesede/CBC/PKCS5Padding )
- pycharm 安装 jupyter
- linux下jupyter notebook路径不对的解决方法
- VS Code 新版本重磅发布,迎来 2020 年首个重大更新!
- MSP430G2553开发板万年历加温湿度
- Automator——为mac创建自定义mac右键菜单
- 数据库语言,转载自:红黑联盟
- 对“鬼压床”现象的科学解释与防治
- Shell实现俄罗斯方块小游戏
- Invalid Host/Origin header vue项目
- STARK Low Degree Testing——FRI
- null与empty区别
- 使用计算机翻译软件,memoQ(计算机翻译工具)
- JSP (java服务器页面)
- Linux学习网站推荐