猿问

今天看到一道很有意思的面试题,想了半天也不得其解,想上来问问大家。

怎么实现一个精准的Timer?

我写了如下的代码进行测试。
1. 在主线程中。

NSTimer *tiemer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(output) userInfo:nil repeats:YES];
- (void) output{    NSLog(@"-------------");
}

发现间隔时间大概在正负5毫秒之间徘徊。
就像这样:

2013-05-02 16:25:32.550 TestDemoArc[21139:907] -------------
2013-05-02 16:25:33.549 TestDemoArc[21139:907] -------------
2013-05-02 16:25:34.554 TestDemoArc[21139:907] -------------
2013-05-02 16:25:35.555 TestDemoArc[21139:907] -------------

如果在主线程中做一些操作,比如:

    int j = 0;
    for (int i = 0; i<100000000; i++) {
        j = j+i;    }

时间间隔会变为两秒。
就像这样:
2013-05-02 16:38:32.437 TestDemoArc[21207:907] -------------
2013-05-02 16:38:34.437 TestDemoArc[21207:907] -------------
2013-05-02 16:38:36.437 TestDemoArc[21207:907] -------------
2013-05-02 16:38:38.439 TestDemoArc[21207:907] -------------
2013-05-02 16:38:40.437 TestDemoArc[21207:907] -------------

当然,用block放到子线程里就只有1毫秒左右的偏差了。
现在想问怎么做一个Timer,保证有在1毫秒以下的偏差。


慕神8447489
浏览 248回答 2
2回答

绝地无双

IOS中可以使用"mach_absolute_time"获取到CPU的tickcount的计数值,可以通过"mach_timebase_info"函数获取到纳秒级的精确度 代码如下: uint64t start = 0; uint64t end = 0; uint64_t elapsed = 0;mach_timebase_info_t&nbsp;timeBaseInfo&nbsp;=&nbsp;mach_timebase_info(info);start&nbsp;=&nbsp;mach_absolute_time();//&nbsp;dosomething //&nbsp;.....end&nbsp;=&nbsp;mach_absolute_time();elapsed&nbsp;=&nbsp;end&nbsp;-&nbsp;start;//&nbsp;convert&nbsp;to&nbsp;nanoseconds uint64_t&nbsp;elapsedNanoSeconds&nbsp;=&nbsp;elapsed&nbsp;*&nbsp;sTimebaseInfo.numer&nbsp;/&nbsp;sTimebaseInfo.denom;但是CPU线程之间的调度肯定要花费时间,所以只能尽可能的精确。

郎朗坤

计时器不准确的原因是,计时器只有在 runLoop 的一次循环中被检查,所以如果在上次循环中做了什么耗时的操作,那么计时器就被延后执行了。正确的方法应该是新开一个线程,然后在新开的线程里设定一个 timer,并执行。__block&nbsp;TestViewController&nbsp;*blockSelf&nbsp;=&nbsp;self;dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,&nbsp;0),&nbsp;^{ &nbsp;&nbsp;&nbsp;&nbsp;blockSelf->_timer=[NSTimer&nbsp;scheduledTimerWithTimeInterval:1.0 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;target:blockSelf &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;selector:@selector(caculateLeftTimeForTomorrow) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;userInfo:nil &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;repeats:YES]&nbsp;; &nbsp;&nbsp;&nbsp;&nbsp;[[NSRunLoop&nbsp;currentRunLoop]&nbsp;addTimer:blockSelf->_timer&nbsp;forMode:NSDefaultRunLoopMode]; &nbsp;&nbsp;&nbsp;&nbsp;[[NSRunLoop&nbsp;currentRunLoop]&nbsp;run]; });
随时随地看视频慕课网APP

相关分类

iOS
我要回答