1.��ʱ Դ��
2.如何实现定时任务- Java Timer/TimerTask 源码解析
3.nodejs 14.0.0源码分析之setTimeout
4.Timer & TimerTask 源码分析
5.java中的定时定时代码任务调度之Timer定时器(案例和源码分析)
��ʱ Դ��
定时器T1定时μs,工作方式设置为方式2,源码用TL1作为8位定时器,器源产生μs的定时定时代码定时,定时初值X为:X=2^8-(* ^6* * ^(-6))/=6TH1=TL1=6H,源码TMOD=H
源代码如下:
MOV TMOD,器源安卓源码分析#H
MOV TH1,#H
MOV TL1,定时定时代码#H
SETB TR1
DS1_RPTA:
MOV R2,源码#H
DS1_RPTB:
JNB TF1,器源$
CLR TF1
CPL P1.3
DJNZ R2,DS1_RPTB
CPL P1.2
LJMP DS1_RPTA
单片机中有两个定时器T0和T1,定时定时代码分别是源码由两个8位的专用寄存器组成,即定时/计数器T0由TH0和TL0组成,器源T1由TH1和TL1组成。定时定时代码单片机中的源码定时器溢出时申请的中断,达到计时或计数的器源目的。并使用定时控制寄存器控制它。其中的:
TF1:定时器1溢出标志。定时/计数器溢出时由硬件置位。中断处理时由硬件清除。或用软件清除。
TF0:定时器0溢出标志。定时/计数器溢出时由硬件置位。中断处理时由硬件清除,或用软件清除。
扩展资料
定时器工作的流程:
以为例用定时器0方式一产生毫秒的定时:
1、确定使用哪个定时器,使用哪种方式,通过TMOD设置,vs的源码TMOD的低四位是设置定时器0的,高四位是用来设置定时器1的,其中的M0,M1是用来设置定时器工作在哪种方式,GATE一般用不要设置,C/T是选择计数模式还是定时模式的,如:TMOD = 0X,就说明定时器0工作在方式1。
2、设置定时的时间,用定时器定时,如:毫秒,可以用这种方式TH0 = ( - ) / ,TL0 = ( - ) % ;可以这样理解:因为这是定时器的初值,也就是说计数脉冲就是在这个数的基础上向上递增,到达后就溢出产生中断。
3、打开中断,使用IE寄存器,首先打开总中断EA = 1,这一步是所有中断所必须的,然后打开定时器0中断,ET0 =1。
4、这时准备工作结束,启动定时器,使用TCON寄存器,如来锁源码TR0 = 1,实现了一个毫秒的定时。
《单片机原理及应用》 曹巧媛 编著 电子工业出版社 第四章 单片机定时功能及应用 第一节 定时器/计数器的结构与工作原理 第二节 定时计数器的操作模式及应用 第三节 定时器综合应用举例
百度百科--定时器中断
如何实现定时任务- Java Timer/TimerTask 源码解析
日常实现各种服务端系统时,我们一定会有一些定时任务的需求。比如会议提前半小时自动提醒,异步任务定时/周期执行等。那么如何去实现这样的一个定时任务系统呢? Java JDK提供的Timer类就是一个很好的工具,通过简单的API调用,我们就可以实现定时任务。
现在就来看一下java.util.Timer是如何实现这样的定时功能的。
首先,我们来看一下一个使用demo
基本的使用方法:
加入任务的API如下:
可以看到API方法内部都是调用sched方法,其中time参数下一次任务执行时间点,是通过计算得到。period参数为0的话则表示为一次性任务。
那么我们来看一下Timer内部是如何实现调度的。
内部结构
先看一下Timer的组成部分:
Timer有3个重要的模块,分别是 TimerTask, TaskQueue, TimerThread
那么,在加入任务之后,整个Timer是怎么样运行的呢?可以看下面的示意图:
图中所示是简化的逻辑,多个任务加入到TaskQueue中,会自动排序,队首任务一定是当前执行时间最早的任务。TimerThread会有一个一直执行的循环,从TaskQueue取队首任务,判断当前时间是否已经到了任务执行时间点,如果是周期率源码则执行任务。
工作线程
流程中加了一些锁,用来避免同时加入TimerTask的并发问题。可以看到sched方法的逻辑比较简单,task赋值之后入队,队列会自动按照nextExecutionTime排序(升序,排序的实现原理后面会提到)。
从mainLoop的源码中可以看出,基本的流程如下所示
当发现是周期任务时,会计算下一次任务执行的时间,这个时候有两种计算方式,即前面API中的
优先队列
当从队列中移除任务,或者是修改任务执行时间之后,队列会自动排序。始终保持执行时间最早的任务在队首。 那么这是如何实现的呢?
看一下TaskQueue的源码就清楚了
可以看到其实TaskQueue内部就是基于数组实现了一个最小堆 (balanced binary heap), 堆中元素根据 执行时间nextExecutionTime排序,执行时间最早的任务始终会排在堆顶。这样工作线程每次检查的任务就是当前最早需要执行的任务。堆的初始大小为,有简单的倍增扩容机制。
TimerTask 任务有四种状态:
Timer 还提供了cancel和purge方法
常见应用
Java的Timer广泛被用于实现异步任务系统,在一些开源项目中也很常见, 例如消息队列RocketMQ的 延时消息/消费重试 中的异步逻辑。
上面这段代码是RocketMQ的延时消息投递任务 ScheduleMessageService 的核心逻辑,就是使用了Timer实现的异步定时任务。
不管是实现简单的异步逻辑,还是构建复杂的任务系统,Java的偷源码卖Timer确实是一个方便实用,而且又稳定的工具类。从Timer的实现原理,我们也可以窥见定时系统的一个基础实现:线程循环 + 优先队列。这对于我们自己去设计相关的系统,也会有一定的启发。
nodejs .0.0源码分析之setTimeout
本文深入剖析了Node.js .0.0版中定时器模块的实现机制。在.0.0版本中,Node.js 对定时器模块进行了重构,改进了其内部结构以提高性能和效率。下面将详细介绍定时器模块的关键组成部分及其实现细节。 首先,让我们了解一下定时器模块的组织结构。Node.js 采用了链表和优先队列(二叉堆)的组合来管理定时器。链表用于存储具有相同超时时间的定时器,而优先队列则用来高效地管理这些链表。 链表通过 TimersList数据结构进行管理,它允许将具有相同超时时间的定时器归类到同一队列中。这样,Node.js 能够快速定位并处理即将到期的定时器。 为了进一步优化性能,Node.js 使用了一个优先队列(二叉堆)来管理所有链表。在这个队列中,每个链表对应一个节点,根节点表示最快到期的定时器。在时间循环(timer阶段)时,Node.js 会从二叉堆中查找超时的节点,并执行相应的回调函数。 为了实现这一功能,Node.js 还维护了一个超时时间到链表的映射,以确保快速访问和管理定时器。 接下来,我们将从 setTimeout函数的实现开始分析。这个函数主要涉及 new Timeout和 insert两个操作。其中,new Timeout用于创建一个对象来存储定时器的上下文信息,而 insert函数则用于将定时器插入到优先队列中。 具体地,Node.js 使用了 scheduleTimer函数来封装底层计时操作。这个函数通过将定时器插入到libuv的二叉堆中,为每个定时器指定一个超时时间(即最快的到期时间)。在执行时间循环时,libuv会根据这个时间判断是否需要触发定时器。 当定时器触发时,Node.js 会调用 RunTimers函数来执行回调。回调函数是在Node.js初始化时设置的,负责处理定时器触发时的具体逻辑。在回调函数中,Node.js 遍历优先队列以检查是否有其他未到期的定时器,并相应地更新libuv定时器的时间。 最后,Node.js 在初始化时通过设置 processTimers函数作为超时回调来确保定时器的正确执行。通过这种方式,Node.js 保证了定时器模块的初始化和定时器触发时的执行逻辑。 本文通过详尽的分析,展示了Node.js .0.0版中定时器模块的内部机制,包括其组织结构、数据管理和回调处理等关键方面。虽然本文未涵盖所有细节,但对于理解Node.js定时器模块的实现原理提供了深入的洞察。对于进一步探索Node.js定时器模块的实现,特别是与libuv库的交互,后续文章将提供更详细的分析。Timer & TimerTask 源码分析
尽管 Timer 已经在现代 Java 开发中鲜少使用,但其内部结构对理解和实现自动化流程有着重要参考价值。这篇源码分析着重于 Timer 和 TimerTask 的工作原理,它们通过维护一个 TaskQueue,确保任务按照预设时间执行,其中的并发处理策略对初学者极具启发性。
在 Timer 类中,每个 Timer 实例对应一个单独的线程,这可能导致任务执行顺序受阻。Timer 的生命周期不确定,任务完成后可能不会立即回收,而 ScheduledThreadPoolExecutor 是推荐的替代方案。Timer 是线程安全的,但不保证任务执行的实时性,而是依赖于 wait() 等待机制。TaskQueue 是 TimerThread 的核心,它负责调度任务的执行。
TimerThread 是负责执行任务的线程,继承自 Thread,其简洁的实现表明了其功能的专注。Timer 的构造器和 schedule 方法提供多种重载形式,而 sched 方法是它们的最终调用者。TimerTask 是一个抽象类,实现了 Runnable,用户需创建其子类并覆盖 run 方法,定义了任务的状态标识和执行时间属性。
尽管 Timer 已经过时,但理解其内部机制有助于在需要定时任务的场景中找到更高效、可靠的解决方案。
java中的任务调度之Timer定时器(案例和源码分析)
定时器在日常生活中如同闹钟般常见,用于在特定时间执行任务或重复执行同一任务。在Java中,内置的定时任务器 Timer 是实现此功能的强大工具。本文将深入探讨 Timer 的基本使用、源码分析及其局限性。 一、Timer 基本使用 在 Java 中,通过 Timer 实现定时任务时,主要涉及到 Timer 和 TimerTask 这两个类。Timer 负责管理任务的执行,而 TimerTask 则包含具体任务的实现。使用步骤如下: 1. 创建 Timer。 2. 创建 TimerTask 并实现业务逻辑。 3. 使用 Timer 的 schedule 方法执行 TimerTask,可以指定开始执行时间、间隔时间等参数。 例如,创建一个在 2 秒后执行、每隔 1 秒执行一次的 TimerTask: javaTimer timer = new Timer();
TimerTask myTask = new MyTask();
timer.schedule(myTask, L, L);
二、Timer 源码分析 深入剖析 Timer 的源码有助于理解其内部机制。Timer 类内部包含 TaskQueue 和 TimerThread 两个关键组件。 1. **TaskQueue**:这是一个最小堆,存放 Timer 的所有 TimerTask。根据每个 TimerTask 的 nextExecutionTime(下次执行开始时间)决定其在堆中的位置。nextExecutionTime 越小,任务越有可能先执行。 2. **TimerThread**:执行 TaskQueue 中的任务后,将任务从队列中移除。 TimerTask 的位置决定于其 nextExecutionTime,确保优先执行执行时间最早的任务。此外,Timer 默认大小为 个任务。 构造方法包括默认构造、是否为守护线程、带名字的构造、带名字和是否为守护线程的构造。 定时任务方法包括: 1. schedule(task, time):在时间等于或超过 time 时执行 task 且仅执行一次。 2. schedule(task, time, period):首次在 time 时执行 task,之后每隔 period 毫秒重复执行。 3. schedule(task, delay):在 delay 时间后执行 task 且仅执行一次。 4. schedule(task, delay, period):在 delay 后开始首次执行 task,之后每隔 period 毫秒重复执行。 执行定时任务的核心在于队列的维护和优先级调度。此外,还存在 scheduleAtFixedRate 方法,其行为与 scheduleAtFixedRate 类似,但考虑了任务执行所需时间的并发性。 三、Timer 缺陷 尽管 Timer 提供了基本的定时任务功能,但存在一些局限性: 1. **线程管理不足**:当多个任务执行时间过长,且时间间隔不一致时,可能会导致任务执行顺序与预期不符,影响任务调度效率。 2. **异常处理机制**:当 TimerTask 抛出 RuntimeException,所有任务都会停止执行,缺乏异常恢复机制。 为了克服这些缺陷,出现了更高级的 Timer 替代品 ScheduledExecutorService,以及众多优秀的框架,提供更强大的任务管理和执行能力。未来文章中将详细介绍这些工具及其优势。