执行Timer任务调度方法有如下几种:

这些方法最后调用的都是这个方法:

 private void sched(TimerTask task, long time, long period)

这个方法的作用是将task放入Timer实例的共享变量queue(TaskQueue类型)中。源码如下:
private void sched(TimerTask task, long time, long period) {if (time < 0)throw new IllegalArgumentException("Illegal execution time.");// Constrain value of period sufficiently to prevent numeric// overflow while still being effectively infinitely large.if (Math.abs(period) > (Long.MAX_VALUE >> 1))period >>= 1;synchronized(queue) {if (!thread.newTasksMayBeScheduled)throw new IllegalStateException("Timer already cancelled.");synchronized(task.lock) {if (task.state != TimerTask.VIRGIN)throw new IllegalStateException("Task already scheduled or cancelled");task.nextExecutionTime = time;task.period = period;task.state = TimerTask.SCHEDULED;}queue.add(task);if (queue.getMin() == task)queue.notify();}}

TaskQueue按照一个“完全二叉树堆”来进行排序,完全二叉树堆的中根节点的值最大(或者最小),每节点的值大于(或者小于)其两个子节点。
queue.add(task)时首先将该任务放到队列最后,会发生“上浮”动作,最终保持完全二叉树堆的根节点存放task.nextExecutionTime最小的那个task,如果要执行任务直接从TaskQueue的根节点获取那个值执行,执行完任务后从队列中移除。
这篇文章以图文的方式对二叉树堆算法讲解的很清晰 http://weixin.niurenqushi.com/article/2016-06-17/4326390.html,可以参考一下。
回到源码,sched(TimerTask task, long time, long period) 方法会将一个任务加入到TaskQueue队列后,如果这个任务在队列中的根节点(也就是nextExecutionTime最小的那个task),那就发出notify通知,激活其他占用了该任务由于wait()而阻塞状态的线程。
那这个线程主要涉及那一块呢?答案是Timer的线程体,源码如下:
public void run() {try {mainLoop();} finally {// Someone killed this Thread, behave as if Timer cancelledsynchronized(queue) {newTasksMayBeScheduled = false;queue.clear();  // Eliminate obsolete references}}}/*** The main timer loop.  (See class comment.)*/private void mainLoop() {while (true) {try {TimerTask task;boolean taskFired;synchronized(queue) {// Wait for queue to become non-empty,等待被notify激活while (queue.isEmpty() && newTasksMayBeScheduled)queue.wait();if (queue.isEmpty())break; // Queue is empty and will forever remain; die// Queue nonempty; look at first evt and do the right thinglong currentTime, executionTime;task = queue.getMin();synchronized(task.lock) {if (task.state == TimerTask.CANCELLED) {queue.removeMin();continue;  // No action required, poll queue again}currentTime = System.currentTimeMillis();executionTime = task.nextExecutionTime;// 任务执行时间已经到达if (taskFired = (executionTime<=currentTime)) {if (task.period == 0) { // 如果period=0,则任务进行一次便结束,并移出队列queue.removeMin();task.state = TimerTask.EXECUTED;} else { // 设置下一次执行的时间// task.period<0 对应 scheduleAtFixedRate 方法// task.period>0 对应 schedule 方法queue.rescheduleMin(task.period<0 ? currentTime   - task.period: executionTime + task.period);}}}// 任务执行时间没到,等待,直到下一次执行时间大于当前时间if (!taskFired) queue.wait(executionTime - currentTime);}// 执行任务时间到达,开始执行任务,没有加锁,并发执行if (taskFired)  // Task fired; run it, holding no lockstask.run();} catch(InterruptedException e) {}}}

  

转载于:https://www.cnblogs.com/chenjunjie12321/p/8671303.html

schedule与scheduleAtFixedRate之Timer源码分析相关推荐

  1. 【Android 异步操作】Timer 定时器 ( Timer 与 TimerTask 基本使用 | Timer 定时器常用用法 | Timer 源码分析 )

    文章目录 一.Timer 定时器基本使用 二.Timer 定时器常用用法 三.Timer 源码分析 四.Timer 部分源码注释 五.源码及资源下载 参考文档 : Timer 定时器 API 文档 T ...

  2. java刷卡计时计次源码美萍_Java 定时调配 Timer 类和定任务 TimerTask 类(一篇详细且完整的源码分析以及四种简单的使用方法)...

    前言 在我们日常生活中,我们常常会遇到有关计时器的事情.如商城类项目会在某年某月某日某时某分某秒进行特价活动,那么当时间到达这个时间点上的时候该事件就会触发. 1.Timer 类构造函数摘要 1 Ti ...

  3. storm启动nimbus源码分析-nimbus.clj

    storm启动nimbus源码分析-nimbus.clj nimbus是storm集群的"控制器",是storm集群的重要组成部分.我们可以通用执行bin/storm nimbus ...

  4. Nimbus二storm启动nimbus源码分析-nimbus.clj

    nimbus是storm集群的"控制器",是storm集群的重要组成部分.我们可以通用执行bin/storm nimbus >/dev/null 2>&1 &a ...

  5. storm启动supervisor源码分析-supervisor.clj

    storm启动supervisor源码分析-supervisor.clj supervisor是storm集群重要组成部分,supervisor主要负责管理各个"工作节点".sup ...

  6. Java定时任务(一) Timer及TimerTask的案例解析及源码分析

    Java定时任务(一)  Timer及TimerTask的案例解析及源码分析 一.概述: 定时任务这个概念在Java的学习以及项目的开发中并不陌生,应用场景也是多种多样.比如我们会注意到12306网站 ...

  7. Zookeeper源码分析(二) ----- zookeeper日志

    zookeeper源码分析系列文章: Zookeeper源码分析(一) ----- 源码运行环境搭建 原创博客,纯手敲,转载请注明出处,谢谢! 既然我们是要学习源码,那么如何高效地学习源代码呢?答案就 ...

  8. RocketMQ源码分析之延迟消息

    文章目录 前言 一.延迟消息 1.特点 2.使用场景 3.demo 二.发送延迟消息 三.broker端存储延迟消息 四.总结 1.延迟消息工作原理 2.延迟消息在消费者消费重试中的应用 前言 本篇文 ...

  9. Netty学习十七:源码分析之HashWheelTimer

    一.常见定时任务实现 定时器的使用场景包括:成月统计报表.财务对账.会员积分结算.邮件推送等,它一般有三种表现形式:按固定周期定时执行.延迟一定时间后执行.指定某个时刻执行. 定时器的本质是设计一种数 ...

  10. golang源码分析-调度概述

    golang源码分析-调度过程概述 本文主要概述一下golang的调度器的大概工作的流程,众所周知golang是基于用户态的协程的调度来完成多任务的执行.在Linux操作系统中,以往的多线程执行都是通 ...

最新文章

  1. 博客基础_django_python从入门到实践_创建项目_创建应用
  2. 金蝶K/3 同步用核算项目配置
  3. Oracle里schema理解
  4. 2018~2019-11 20165107 网络对抗技术期末免考 Exp10 Final Powershell学习应用与渗透实践...
  5. sql遍历所有数据集
  6. python del函数_python中del函数的垃圾回收
  7. Python json模块 - Python零基础入门教程
  8. 浏览器拦截跨域请求处理方法(已阻止跨源请求:同源策略禁止读取远程资源)
  9. 【今日CS 视觉论文速览】10 Jan 2019
  10. sass webpack_如何在Visual Studio和Webpack中编译Sass文件
  11. github(GitHub Flavored Markdown)
  12. 图书馆的uml概念类图怎么画_设计模式:UML?设计原则?
  13. 快速搭建dajango框架
  14. 小米平板位置服务器,小米平板 2
  15. 算法入门——排序算法
  16. 已知X随机变量的情况下,求解Y=G(x)的概率分布函数(只考虑单调的情况)
  17. 黑鲨helo支持html吗,黑鲨2和黑鲨helo区别买哪个好
  18. php for循环写三角形,【杂谈】PHP运用for轮回输出三角形
  19. 《数据挖掘》读书笔记2、3章节
  20. 【开源】STM32硬盘音圈电机闭环控制

热门文章

  1. 基于Quartz.Net的任务管理平台开发(3) —— 任务管理平台
  2. bitnami_redmine3.3.0-1 问题及备份恢复
  3. C# BackgroundWorker组件学习
  4. 免费CMS系统的广告如何去掉
  5. 学习pytorch: 数据加载和处理
  6. 亲测有效!实现Chrome浏览器下载速度提升3倍!
  7. ubuntu 下安装 phpmyadmin 过程记录
  8. 关于EasyRecovery的一些高级设置
  9. 如何整理写作思路?MindManager在文章写作方面的应用
  10. Tuxera NTFS对磁盘进行不同格式转换