版本比较

标识

  • 该行被添加。
  • 该行被删除。
  • 格式已经改变。

...

3. 程序运行后维护一个周期性触发的tick信号,比如利用alarm函数周期性触发ALARM信号,在信号处理函数中从头遍历定时器链表,判断定时器是否超时。如果定时器超时,则记录下该定时器,然后将其从链表中删除。

4. 执行所有超时定时器的回调函数。执行所有超时的定时器的回调函数。


以上就是一个基于升序链表的定时器实现,这种方式添加定时器的时间复杂度是O(n),删除定时器的时间复杂度是O(1),执行定时任务的时间复杂度是O(1)。

tick信号的周期对定时器的性能有较大的影响,当tick信号周期较小时,定时器精度高,但CPU负担较高,因为要频繁执行信号处理函数;当tick信号周期较大时,CPU负担小,但定时精度差。

当定时器数量较多时,链表插入操作开销比较大。

时间轮

与上面的升序链表实现方式类似,也需要维护一个周期性触发的tick信号,但不同的是,定时器不再组织成链表结构,而是按各自的超时时间,通过散列分布到不同的时间轮上,像下面这样:与上面的升序链表实现方式类似,也需要维护一个周期性触发的tick信号,但不同的是,定时器不再组织成单链表结构,而是按照超时时间,通过散列分布到不同的时间轮上,像下面这样:

上面的时间轮包含N个槽位,每个槽位上都有一个定时器链表。时间轮以恒定的速度顺时针转动,每转一步,表盘上的指针就指向下一个槽位。每次转动对应一个tick,它的周期为si,一个共有N个槽,所以它运转一周的时间是N*si。

每个槽位都有一条定时器链表,同一条链表上的每个定时器都具有相同的特征:它们的定时时间相差N每个槽位都有一条定时器链表,同一条链表上的每个定时器都具有相同的特征:前后节点的定时时间相差N*si的整数倍。时间轮正是利用这个关系将定时器散列到不同的链表上。假如现在指针指向槽cs,我们要添加一个定时时间为ti的定时器,则该定时器将被插入槽ts(time slot)对应的链表中:

...