定时器概述
后台服务端逻辑一般由两种事件触发,一个是网络事件,另一个是定时事件。通常有两种框架:
第一种:网络事件和定时事件在同一个线程内处理,如nginx、redis;
第二种:网络事件和定时事件在不同的线程内处理,如skynet;
// 第⼀种
while (!quit) {
int now = get_now_time();// 单位:ms
int timeout = get_nearest_timer() - now;
if (timeout < 0) timeout = 0;
int nevent = epoll_wait(epfd, ev, nev, timeout);
for (int i=0; i<nevent; i++) {
//... ⽹络事件处理
}
update_timer(); // 时间事件处理
}
// 第⼆种 在其他线程添加定时任务
void* thread_timer(void * thread_param) {
init_timer();
while (!quit) {
update_timer(); // 更新检测定时器,并把定时事件发送到消息队列中
sleep(t); // 这⾥的 t 要⼩于 时间精度
}
clear_timer();
return NULL;
}
pthread_create(&pid, NULL, thread_timer, &thread_param);
定时器的应用
- 心跳检测
- 技能冷却
- 其他需要超时的定时任务
定时器的本质
越近触发的任务,优先级越高
定时器设计
- 初始化定时器
- 添加定时器
- 删除定时任务
- 检测定时任务
定时器的实现
- 红黑树
- 最小堆
- 时间轮