linux上点时间延时,linux 延时及时间函数总结 (转)

一、 基础知识

1、时间类型。Linux下常用的时间类型有4个:time_t,struct timeval,struct

timespec,struct tm。

(1)time_t是一个长整型,一般用来表示用1970年以来的秒数。

(2)Struct timeval有两个成员,一个是秒,一个是微妙。

a4c26d1e5885305701be709a3d33442f.pngstruct timeval{

a4c26d1e5885305701be709a3d33442f.pnglongtv_sec;a4c26d1e5885305701be709a3d33442f.pnglongtv_usec;a4c26d1e5885305701be709a3d33442f.png

};

(3)struct timespec有两个成员,一个是秒,一个是纳秒。

a4c26d1e5885305701be709a3d33442f.pngstruct timespec{

a4c26d1e5885305701be709a3d33442f.png time_t tv_sec;a4c26d1e5885305701be709a3d33442f.pnglongtv_nsec;a4c26d1e5885305701be709a3d33442f.png

};

(4)struct tm是直观意义上的时间表示方法:

a4c26d1e5885305701be709a3d33442f.pngstruct tm{

a4c26d1e5885305701be709a3d33442f.pnginttm_sec;a4c26d1e5885305701be709a3d33442f.pnginttm_min;a4c26d1e5885305701be709a3d33442f.pnginttm_hour;a4c26d1e5885305701be709a3d33442f.pnginttm_mday;a4c26d1e5885305701be709a3d33442f.pnginttm_mon;a4c26d1e5885305701be709a3d33442f.pnginttm_year;a4c26d1e5885305701be709a3d33442f.pnginttm_wday;a4c26d1e5885305701be709a3d33442f.pnginttm_yday;a4c26d1e5885305701be709a3d33442f.pnginttm_isdst;a4c26d1e5885305701be709a3d33442f.png

};

2、 时间操作

(1) 时间格式间的转换函数

主要是 time_t、struct tm、时间的字符串格式之间的转换。看下面的函数参数类型以及返回值类型:

a4c26d1e5885305701be709a3d33442f.pngchar*asctime(conststruct tm*tm);

a4c26d1e5885305701be709a3d33442f.pngchar*ctime(consttime_t*timep);

a4c26d1e5885305701be709a3d33442f.pngstruct tm*gmtime(consttime_t*timep);

a4c26d1e5885305701be709a3d33442f.pngstruct tm*localtime(consttime_t*timep);

a4c26d1e5885305701be709a3d33442f.pngtime_t mktime(struct tm*tm);

gmtime和localtime的参数以及返回值类型相同,区别是前者返回的格林威治标准时间,后者是当地时间。

(2) 获取时间函数

两个函数,获取的时间类型看原型就知道了:

a4c26d1e5885305701be709a3d33442f.pngtime_t time(time_t*t);

a4c26d1e5885305701be709a3d33442f.pngintgettimeofday(struct timeval*tv, struct timezone*tz);

前者获取time_t类型,后者获取struct

timeval类型,因为类型的缘故,前者只能精确到秒,后者可以精确到微秒。

二、 延迟函数

主要的延迟函数有:sleep(),usleep(),nanosleep(),select(),pselect().

a4c26d1e5885305701be709a3d33442f.pngunsignedintsleep(unsignedintseconds);

a4c26d1e5885305701be709a3d33442f.pngvoidusleep(unsignedlongusec);

a4c26d1e5885305701be709a3d33442f.pngintnanosleep(conststruct timespec*req, struct timespec*rem);

a4c26d1e5885305701be709a3d33442f.pngintselect(intn, fd_set*readfds, fd_set*writefds, fd_set*exceptfds,struct timeval*timeout);

a4c26d1e5885305701be709a3d33442f.pngintpselect(intn, fd_set*readfds, fd_set*writefds, fd_set*exceptfds,conststruct timespec*timeout,constsigset_t*sigmask);

alarm函数是信号方式的延迟,这种方式不直观,这里不说了。

仅通过函数原型中时间参数类型,可以猜测sleep可以精确到秒级,usleep/select可以精确到微妙级,nanosleep和pselect可以精确到纳秒级。

而实际实现中,linux上的nanosleep和alarm相同,都是基于内核时钟机制实现,受linux内核时钟实现的影响,并不能达到纳秒级的精度,man

nanosleep也可以看到这个说明,man里给出的精度是:Linux/i386上是10 ms

,Linux/Alpha上是1ms。

这里有一篇文章http://blog.csdn.net/zhoujunyi/archive/2007/03/30/1546330.aspx,测试了不同延迟函数之间的精确度。文章给出的结论是linux上精度最高的是select,10ms级别。我在本机器测试select和pselect相当,都达到了1ms级的精度,精度高于文章中给出的10ms,sleep在秒级以上和usleep/nanosleep相当。下面贴下我机器上1ms时候的测试结果,其他不贴了:

a4c26d1e5885305701be709a3d33442f.pngsleep10000-1000a4c26d1e5885305701be709a3d33442f.pngusleep100029741974a4c26d1e5885305701be709a3d33442f.pngnanosleep100029901990a4c26d1e5885305701be709a3d33442f.pngselect1000991-9a4c26d1e5885305701be709a3d33442f.pngpselect1000990-10a4c26d1e5885305701be709a3d33442f.pnggettimeofday100010000

而使用gettimeofday循环不停检测时间,可精确微秒级,不过不适宜用来做定时器模块。

因此后面的定时期模块将选择select为延迟函数。

三、 定时器模块需求以及实现概述

1、需求。从实现结果的角度说来,需求就是最终的使用方式。呵呵,不详细描述需求了,先直接给出我实现的CTimer类的三个主要接口:

a4c26d1e5885305701be709a3d33442f.pngClass CTimer{

a4c26d1e5885305701be709a3d33442f.pngPublic:

a4c26d1e5885305701be709a3d33442f.pngCTimer(unsignedintvinterval,void(*vfunc)(CTimer*,void*),void*vdata,TimerType vtype);

a4c26d1e5885305701be709a3d33442f.pngvoidstart();

a4c26d1e5885305701be709a3d33442f.pngvoidstop();

a4c26d1e5885305701be709a3d33442f.pngvoidreset(unsignedintvinterval);

a4c26d1e5885305701be709a3d33442f.png

};

使用定时器模块的步骤如下:

(1) 实例化一个CTimer,参数的含义依次是:vinterval间隔时间(单位ms),vfunc是时间到回调的函数,vdata回调函数使用的参数,vtype定时器的类型,分一次型和循环型两种。

(2) 调用start方法。

(3) 必要的时候调用stop和reset。

2、实现。简单描述下定时器模块的实现,有一个manager单例类保存所有CTimer对象,开启一线程运行延迟函数,每次延迟间隔到,扫描保存CTimer的容器,对每个CTimer对象执行减少时间操作,减少到0则执行回调函数。对一次性CTimer,超时则从容器中删除,循环型的将间隔时间重置,不从容器中移除。

CTimer的start执行将对象插入到manager容器中操作;stop执行将对象从manager容器中删除的操作;reset执行先删除,重置间隔,然后再放到容器中,reset不改变CTimer的定时器类型属性。

四、 定时器模块的数据结构选择

Manager类的容器要频繁进行的操作涉及插入、删除、查询等。

误区:(1)简单看,好象该容器要是有序的,方便插入删除等,貌似红黑树比较合适。其实不然,插入删除操作的频率很低,最频繁的还是每次时延到,对容器的扫描并做时间减少操作,红黑树在做顺序扫描相对链表并没什么优势。

(2) 插入的时候依照顺序链表的方式插入到合适的位置保持排序,以保证超时的对象都在链表的头端。其实这也是没必要的,每次时延到,对每一个对象都要做时间减少操作,因此不管是有序还是无序,都是一次扫描就执行完下面操作:减少时间、判断是否超时,是则执行回调,继续判断是什么类型,一次型的则执行完就移除,循环型则执行完直接重置间隔就可。

因此,只需要能快速插入头、删除结点、遍历就好。我的实现直接使用BSD内核中的数据结构LIST,插入头、删除时间复杂度都是1,遍历就不说了。linux下/usr/include/sys下有头文件queue.h里也有LIST结构以及操作的定义。貌似linux下的少了遍历宏:

a4c26d1e5885305701be709a3d33442f.png#define LIST_FOREACH(var, head, field) \

a4c26d1e5885305701be709a3d33442f.pngfor((var)=LIST_FIRST(head); \

a4c26d1e5885305701be709a3d33442f.png (var)!=LIST_END(head); \

a4c26d1e5885305701be709a3d33442f.png (var)=LIST_NEXT(var, field))

五、 详细实现

这里帖出主要的代码,请重点关注CTimerManager::

process方法,不再详细说了。需要详细的全部代码,可来信索取,整体代码很简单,就两个类。

a4c26d1e5885305701be709a3d33442f.pngclassCTimer

a4c26d1e5885305701be709a3d33442f.png{

a4c26d1e5885305701be709a3d33442f.pngfriendclassCTimerManager;

a4c26d1e5885305701be709a3d33442f.pngpublic:

a4c26d1e5885305701be709a3d33442f.png typedefenuma4c26d1e5885305701be709a3d33442f.png{

a4c26d1e5885305701be709a3d33442f.png TIMER_IDLE=0,//start前以及手动调用stop后的状态a4c26d1e5885305701be709a3d33442f.pngTIMER_ALIVE,//在manager的list里时候的状态a4c26d1e5885305701be709a3d33442f.pngTIMER_TIMEOUT//超时后被移除的状态,循环型的没有a4c26d1e5885305701be709a3d33442f.png}TimerState;

a4c26d1e5885305701be709a3d33442f.png typedefenuma4c26d1e5885305701be709a3d33442f.png{

a4c26d1e5885305701be709a3d33442f.png TIMER_ONCE=0,//一次型a4c26d1e5885305701be709a3d33442f.pngTIMER_CIRCLE//循环型a4c26d1e5885305701be709a3d33442f.png}TimerType;

a4c26d1e5885305701be709a3d33442f.png CTimer(unsignedintvinterval,void(*vfunc)(CTimer*,void*),void*vdata,TimerType vtype);

a4c26d1e5885305701be709a3d33442f.pngvoidstart();

a4c26d1e5885305701be709a3d33442f.pngvoidstop();

a4c26d1e5885305701be709a3d33442f.pngvoidreset(unsignedintvinterval);

a4c26d1e5885305701be709a3d33442f.png~CTimer();

a4c26d1e5885305701be709a3d33442f.pngprivate:

a4c26d1e5885305701be709a3d33442f.png unsignedintid_;//测试用a4c26d1e5885305701be709a3d33442f.pngunsignedintm_interval;//间隔,不变a4c26d1e5885305701be709a3d33442f.pngunsignedintm_counter;//开始设置为interval,随延迟时间到,减少a4c26d1e5885305701be709a3d33442f.pngTimerState m_state;//状态a4c26d1e5885305701be709a3d33442f.pngTimerType m_type;//类型a4c26d1e5885305701be709a3d33442f.pngvoid(*m_func)(CTimer*,void*);//回调函数a4c26d1e5885305701be709a3d33442f.pngvoid*m_data;//回调函数参数a4c26d1e5885305701be709a3d33442f.pngLIST_ENTRY(CTimer) entry_;//LIST的使用方式a4c26d1e5885305701be709a3d33442f.png};

a4c26d1e5885305701be709a3d33442f.pnga4c26d1e5885305701be709a3d33442f.pngCTimer::CTimer(unsignedintvinterval,void(*vfunc)(CTimer*,void*),void*vdata,TimerType vtype):

a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png m_interval(vinterval),m_counter(vinterval),

a4c26d1e5885305701be709a3d33442f.png m_state(TIMER_IDLE),m_type(vtype),

a4c26d1e5885305701be709a3d33442f.png m_func(vfunc),m_data(vdata)

a4c26d1e5885305701be709a3d33442f.png{}a4c26d1e5885305701be709a3d33442f.pnga4c26d1e5885305701be709a3d33442f.pngvoidCTimer::start()

a4c26d1e5885305701be709a3d33442f.png{

a4c26d1e5885305701be709a3d33442f.png CTimerManager::instance()->add_timer(this);

a4c26d1e5885305701be709a3d33442f.png

}a4c26d1e5885305701be709a3d33442f.pnga4c26d1e5885305701be709a3d33442f.pngvoidCTimer::stop()

a4c26d1e5885305701be709a3d33442f.png{

a4c26d1e5885305701be709a3d33442f.png CTimerManager::instance()->remove_timer(this);

a4c26d1e5885305701be709a3d33442f.png

}a4c26d1e5885305701be709a3d33442f.pnga4c26d1e5885305701be709a3d33442f.pngvoidCTimer::reset(unsignedintvinterval)

a4c26d1e5885305701be709a3d33442f.png{

a4c26d1e5885305701be709a3d33442f.png CTimerManager::instance()->remove_timer(this);

a4c26d1e5885305701be709a3d33442f.png m_counter=m_interval=vinterval;

a4c26d1e5885305701be709a3d33442f.png CTimerManager::instance()->add_timer(this);

a4c26d1e5885305701be709a3d33442f.png

}a4c26d1e5885305701be709a3d33442f.pnga4c26d1e5885305701be709a3d33442f.pngCTimer::~CTimer()

a4c26d1e5885305701be709a3d33442f.png{

a4c26d1e5885305701be709a3d33442f.pngif(m_state==TIMER_ALIVE)

a4c26d1e5885305701be709a3d33442f.png stop();

a4c26d1e5885305701be709a3d33442f.png

}

CTimerManager的:

a4c26d1e5885305701be709a3d33442f.pngclassCTimerManager

a4c26d1e5885305701be709a3d33442f.png{

a4c26d1e5885305701be709a3d33442f.pngpublic:

a4c26d1e5885305701be709a3d33442f.png a4c26d1e5885305701be709a3d33442f.png typedefenuma4c26d1e5885305701be709a3d33442f.png{

a4c26d1e5885305701be709a3d33442f.png TIMER_MANAGER_STOP=0,

a4c26d1e5885305701be709a3d33442f.png TIMER_MANAGER_START

a4c26d1e5885305701be709a3d33442f.png

}TimerManagerState;

a4c26d1e5885305701be709a3d33442f.png a4c26d1e5885305701be709a3d33442f.pngstaticCTimerManager*instance();

a4c26d1e5885305701be709a3d33442f.pngvoidadd_timer(CTimer*vtimer);//线程安全的adda4c26d1e5885305701be709a3d33442f.pngvoidremove_timer(CTimer*vtimer);//线程安全的removea4c26d1e5885305701be709a3d33442f.pngvoidstart();//开始process线程a4c26d1e5885305701be709a3d33442f.pngvoidstop();//停止process线程a4c26d1e5885305701be709a3d33442f.pngvoiddump();

a4c26d1e5885305701be709a3d33442f.pngprotected:

a4c26d1e5885305701be709a3d33442f.pngstaticvoid*process(void*);//实际的定时器时间延迟线程a4c26d1e5885305701be709a3d33442f.pngprivate: a4c26d1e5885305701be709a3d33442f.pngvoidadd_timer_(CTimer*vtimer);//非线程安全的adda4c26d1e5885305701be709a3d33442f.pngvoidremove_timer_(CTimer*vtimer);//非线程安全的removea4c26d1e5885305701be709a3d33442f.pnga4c26d1e5885305701be709a3d33442f.png CTimerManager();

a4c26d1e5885305701be709a3d33442f.pngstaticpthread_mutex_t m_mutex;

a4c26d1e5885305701be709a3d33442f.pngstaticCTimerManager*m_instance;

a4c26d1e5885305701be709a3d33442f.png a4c26d1e5885305701be709a3d33442f.png TimerManagerState m_state;

a4c26d1e5885305701be709a3d33442f.png LIST_HEAD(,CTimer) list_;//LIST使用方式a4c26d1e5885305701be709a3d33442f.pnga4c26d1e5885305701be709a3d33442f.pngstaticunsignedintmark;//测试,配合dumpa4c26d1e5885305701be709a3d33442f.png};

a4c26d1e5885305701be709a3d33442f.pnga4c26d1e5885305701be709a3d33442f.pngCTimerManager*CTimerManager::instance()

a4c26d1e5885305701be709a3d33442f.png{

a4c26d1e5885305701be709a3d33442f.pngif(m_instance==NULL)

a4c26d1e5885305701be709a3d33442f.png{

a4c26d1e5885305701be709a3d33442f.png pthread_mutex_lock(&m_mutex);

a4c26d1e5885305701be709a3d33442f.pngif(m_instance==NULL)

a4c26d1e5885305701be709a3d33442f.png{

a4c26d1e5885305701be709a3d33442f.png m_instance=newCTimerManager();

a4c26d1e5885305701be709a3d33442f.png

 }a4c26d1e5885305701be709a3d33442f.png pthread_mutex_unlock(&m_mutex);

a4c26d1e5885305701be709a3d33442f.png

 }a4c26d1e5885305701be709a3d33442f.pngreturnm_instance;

a4c26d1e5885305701be709a3d33442f.png

}a4c26d1e5885305701be709a3d33442f.pnga4c26d1e5885305701be709a3d33442f.pngvoidCTimerManager:: start()

a4c26d1e5885305701be709a3d33442f.png{

if(m_state==TIMER_MANAGER_STOP){

a4c26d1e5885305701be709a3d33442f.png m_state=TIMER_MANAGER_START;

a4c26d1e5885305701be709a3d33442f.png pthread_t pid;

a4c26d1e5885305701be709a3d33442f.png pthread_create(&pid,0,process,this);

}

a4c26d1e5885305701be709a3d33442f.png

}a4c26d1e5885305701be709a3d33442f.pnga4c26d1e5885305701be709a3d33442f.pngvoid*CTimerManager:: process(void*arg)

a4c26d1e5885305701be709a3d33442f.png{

a4c26d1e5885305701be709a3d33442f.png pthread_detach(pthread_self());

a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png CTimerManager*manage=(CTimerManager*)arg;

a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png CTimer*item;

a4c26d1e5885305701be709a3d33442f.png struct timeval start,end;

a4c26d1e5885305701be709a3d33442f.png unsignedintdelay;

a4c26d1e5885305701be709a3d33442f.png a4c26d1e5885305701be709a3d33442f.png struct timeval tm;

a4c26d1e5885305701be709a3d33442f.png gettimeofday(&end,0);

a4c26d1e5885305701be709a3d33442f.pnga4c26d1e5885305701be709a3d33442f.pngwhile(manage->m_state==TIMER_MANAGER_START)

a4c26d1e5885305701be709a3d33442f.png{

a4c26d1e5885305701be709a3d33442f.png tm.tv_sec=0;

a4c26d1e5885305701be709a3d33442f.png tm.tv_usec=DEFULT_INTERVAL*1000;

a4c26d1e5885305701be709a3d33442f.png start.tv_sec=end.tv_sec;

a4c26d1e5885305701be709a3d33442f.png start.tv_usec=end.tv_usec;

a4c26d1e5885305701be709a3d33442f.pnga4c26d1e5885305701be709a3d33442f.pngwhile(select(0,0,0,0,&tm)<0&&errno==EINTR);

a4c26d1e5885305701be709a3d33442f.png gettimeofday(&end,0);

a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png delay=(end.tv_sec-start.tv_sec)*1000+(end.tv_usec-start.tv_usec)/1000;

a4c26d1e5885305701be709a3d33442f.png pthread_mutex_lock(&manage->m_mutex);

a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png LIST_FOREACH(item,&(manage->list_), entry_)

a4c26d1e5885305701be709a3d33442f.png{

a4c26d1e5885305701be709a3d33442f.png item->m_counter<delay?item->m_counter=0:item->m_counter-=delay;

a4c26d1e5885305701be709a3d33442f.pngif(item->m_counter==0)

a4c26d1e5885305701be709a3d33442f.png{

a4c26d1e5885305701be709a3d33442f.pngif(item->m_func)

a4c26d1e5885305701be709a3d33442f.png item->m_func(item,item->m_data);

a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.pngif(item->m_type==CTimer::TIMER_ONCE)

a4c26d1e5885305701be709a3d33442f.png{

a4c26d1e5885305701be709a3d33442f.pnga4c26d1e5885305701be709a3d33442f.png manage->remove_timer_(item);

a4c26d1e5885305701be709a3d33442f.png item->m_state=CTimer::TIMER_TIMEOUT;

a4c26d1e5885305701be709a3d33442f.png

 }a4c26d1e5885305701be709a3d33442f.pngelseif(item->m_type==CTimer::TIMER_CIRCLE)

a4c26d1e5885305701be709a3d33442f.png{

a4c26d1e5885305701be709a3d33442f.pnga4c26d1e5885305701be709a3d33442f.png item->m_counter=item->m_interval;

a4c26d1e5885305701be709a3d33442f.png

 }a4c26d1e5885305701be709a3d33442f.png

 }a4c26d1e5885305701be709a3d33442f.png

 }a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png pthread_mutex_unlock(&manage->m_mutex);

a4c26d1e5885305701be709a3d33442f.png

 }a4c26d1e5885305701be709a3d33442f.png

}

六、 讨论

(1)精度问题。精度高,实时性高,但要求select等待的时间缩短,进而增加对LIST结构的扫描操作。精度低,实时性差,但会增加定时器线程的睡眠时间,减少对cpu的占用。一般的应用系统,应该尽量降低精度,避免不必要的扫描,对具体系统可考察所用到的所有定时器的实际间隔,在允许的情况下,尽量降低精度,可通过修改代码中的宏实现。为了降低定时器线程对cpu的占有时间,甚有更为粗犷型的定时器模块实现为将延迟时间取list中最小的那个间隔,保证每次延迟时间到都有回调。

(2)加锁区域问题。本文中的定时器模块实现,将定时器对象的时间减少以及函数回调的执行等再同一个临界区内执行,而有的定时器模块实现是在加锁区域执行“时间减少”操作,将减少到0的对象放到另一个超时链表中,解锁后再单独扫描超时链表执行回调操作。很明显,后者缩短了加锁时间,能及时响应其他的线程的定时器对象的start以及stop操作。但是后者对定时器操作的时序性有误差,直观反应就是可能在定时器执行了stop操作以后,仍然会有超时回调发生,特别是回调参数是指针的情况,可能引起难以发现的bug,增加调试困难。在衡量两者的利弊后,本文采用延长加锁时间以保证操作的时序性。因此,在实际的使用,回调函数应尽快返回,另一方面,尽量减少系统内使用的定时器数目,这个主要原因是延迟时间到要扫描LIST,哪种方式都避免不了。

七、使用示例

a4c26d1e5885305701be709a3d33442f.png#include"timer_manager.h"a4c26d1e5885305701be709a3d33442f.png#include<stdio.h>a4c26d1e5885305701be709a3d33442f.png#include<unistd.h>a4c26d1e5885305701be709a3d33442f.png#include<stdlib.h>a4c26d1e5885305701be709a3d33442f.pngvoidfunc(CTimer*timer,void*data)

a4c26d1e5885305701be709a3d33442f.png{

a4c26d1e5885305701be709a3d33442f.png printf("hi,%d\n",(int)(data));

a4c26d1e5885305701be709a3d33442f.png

}a4c26d1e5885305701be709a3d33442f.pnga4c26d1e5885305701be709a3d33442f.pngintmain()

a4c26d1e5885305701be709a3d33442f.png{

a4c26d1e5885305701be709a3d33442f.png CTimerManager::instance()->start();

a4c26d1e5885305701be709a3d33442f.png CTimer a(1000,func,(void*)1,CTimer::TIMER_CIRCLE);

a4c26d1e5885305701be709a3d33442f.png CTimer a1(2000,func,(void*)11,CTimer::TIMER_ONCE);

a4c26d1e5885305701be709a3d33442f.png CTimer a2(3000,func,(void*)12,CTimer::TIMER_ONCE);

a4c26d1e5885305701be709a3d33442f.png CTimer a3(1000,func,(void*)13,CTimer::TIMER_ONCE);

a4c26d1e5885305701be709a3d33442f.png a4c26d1e5885305701be709a3d33442f.png a.start();

a4c26d1e5885305701be709a3d33442f.png a1.start();

a4c26d1e5885305701be709a3d33442f.png a2.start();

a4c26d1e5885305701be709a3d33442f.png a3.start();

a4c26d1e5885305701be709a3d33442f.png a.start();

a4c26d1e5885305701be709a3d33442f.png a1.start();

a4c26d1e5885305701be709a3d33442f.png a2.start();

a4c26d1e5885305701be709a3d33442f.png a3.start();

a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png sleep(1);

a4c26d1e5885305701be709a3d33442f.png CTimerManager::instance()->dump();

a4c26d1e5885305701be709a3d33442f.png sleep(1);

a4c26d1e5885305701be709a3d33442f.png CTimerManager::instance()->dump();

a4c26d1e5885305701be709a3d33442f.png a.reset(2000);

a4c26d1e5885305701be709a3d33442f.png a1.stop();

a4c26d1e5885305701be709a3d33442f.png a3.stop();

a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png sleep(10);

a4c26d1e5885305701be709a3d33442f.pngreturn0;

a4c26d1e5885305701be709a3d33442f.png

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值