从Timer中学习优先队列的实现

Timer是Java定时器的实现,用来调度定时执行的任务和执行一次的任务,就像JavaScript的setIntervalsetTimeout的意思,它也可以作为后台程序(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()

最重要的两个是fixDownfixUp,表示从queue[k]节点位置开始demotingpromoting

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;}}

promotingdemoting简单一点,只需要比较queue[k]queue[j]两个节点,然后做交换即可。

TaskQueue other methods

通过fixUpfixDown的方法可以保证整个优先队列的关系,保证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中学习优先队列的实现相关推荐

  1. 从 bug 中学习:六大开源项目告诉你 go 并发编程的那些坑

    作者:richardyao,腾讯 CSIG 后台开发工程师 并发编程中,go 不仅仅支持传统的通过共享内存的方式来通信,更推崇通过channel来传递消息,这种新的并发编程模型会出现不同于以往的bug ...

  2. 随想录(在实践中学习kernel代码)

    [声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 记得我在读书的时候,虽然老师也教过操作系统的课程,但是自己的理解却不是很充分,实践部分的内容就更 ...

  3. 《从案例中学习JavaScript》之实现对话效果

    今天突发奇想,js能不能通过字符串和定时器来实现游戏中的对话效果呢.试了一下,还真挺好玩的. 上效果图: 本节涉及的知识点: 字符串的charAt方法 js定时器setInterval(轮询) ### ...

  4. linux服务器中学习使用FFmpeg命令overlay滤镜用法

    linux服务器中学习使用FFmpeg命令overlay滤镜用法 1.overlay技术简介 2.命令行用法 2.1 视频中叠加图标 2.1.1 直接叠加图标 2.1.2 延时叠加图标 2.2 视频中 ...

  5. 我们从工程项目中学习什么?

     这个题目有点大,我在此仅限于技术层面. 这篇文章呢很早就想写,真正促使我付诸行动的是大约两个月前我开始给Mimas team讲街机模拟器的设计,大家普遍很漠然,大概完全搞不懂我为什么要讲这种东东 ...

  6. 浙大吴飞教授:尽管AlphaGo Zero已强大到从经验中学习模型,我也绝不赞同马斯克和霍金的威胁论,人才是智能的最终主宰

    记者 | 鸽子 在整个采访过程中,吴飞教授在回答中给人的最大感受是温和.儒雅.他没有激烈的言辞,也没有犀利的观点,不会一开始直接抛出自己的判断,而是将所有的提问,看作是一次学术上的严谨探讨,从问题本身 ...

  7. 《从缺陷中学习C/C++》——6.15 试图产生的指针很可能不存在

    本节书摘来自异步社区出版社<从缺陷中学习C/C++>一书中的第6章,第6.15节,作者: 刘新浙 , 刘玲 , 王超 , 李敬娜 , ,更多章节内容可以访问云栖社区"异步社区&q ...

  8. rust墙壁升级点什么_分享:如何在阅读Rust项目源码中学习

    今天做了一个Substrate相关的小分享,公开出来. 因为我平时也比较忙,昨天才选定了本次分享的主题,准备比较仓促,细节可能不是很充足,但分享的目的也是给大家提供一个学习的思路,更多的细节大家可以在 ...

  9. 极客新闻——05、如何在工作中学习和成长?

    本文笔记全部来自<极客新闻>--新鲜的技术资讯.权威的趋势剖析.别样的技术洞察 关于如何进行自我学习的话题? 不同的人可能有不同的回答,总结起来就是阅读博客.参加技术大会.读书.利用闲暇时 ...

  10. 3D U-Net:从稀疏注释中学习密集的体积分割

    作者:Tom Hardy Date:2020-01-10 来源:3D U-Net:从稀疏注释中学习密集的体积分割

最新文章

  1. java 服务器发布_我如何在java中发布到服务器?
  2. ldap集成nginx
  3. Vue002_计算属性和监视
  4. 数字和为sum的方法数-01背包计数问题
  5. 判断请求来自手机还是PC
  6. java的et5_Javascript与java相同的3des加密(使用etdesede/CBC/PKCS5Padding )
  7. pycharm 安装 jupyter
  8. linux下jupyter notebook路径不对的解决方法
  9. VS Code 新版本重磅发布,迎来 2020 年首个重大更新!
  10. MSP430G2553开发板万年历加温湿度
  11. Automator——为mac创建自定义mac右键菜单
  12. 数据库语言,转载自:红黑联盟
  13. 对“鬼压床”现象的科学解释与防治
  14. Shell实现俄罗斯方块小游戏
  15. Invalid Host/Origin header vue项目
  16. STARK Low Degree Testing——FRI
  17. null与empty区别
  18. 使用计算机翻译软件,memoQ(计算机翻译工具)
  19. JSP (java服务器页面)
  20. Linux学习网站推荐

热门文章

  1. 1口百兆光纤收发器工业导轨式发送机接收机1百兆光1百兆电工业以太网光纤收发器
  2. 线性表的链式存储结构
  3. Python实现快速大文件比较代码解析
  4. matlab鼠标箭头黑色,个性化的黑色箭头鼠标指针(falchion光标)安装版本
  5. eyoucms相关问题总结
  6. TXT文本 本地词典
  7. 基于ANSYS-APDL的简单静力学分析示例(悬臂梁)
  8. xrd精修教程_XRD精修干货和三元材料的XRD精修实例
  9. excel多元线性拟合_急!!!用excel做的多元线性回归分析~|excle做三元回归
  10. Studio 3T无限试用