Run Loop
运行循环
app 程序只有不停地运行, 能力一直响应用户的操作
Run Loop 两大性能:
- 睡眠中,期待音讯
- 解决音讯
从睡眠中 -> 解决音讯, 须要一个唤醒的过程
1、 讲讲 RunLoop, 我的项目中有用到吗?
RunLoop 的根本作用:
放弃程序的继续运行
节俭 CPU 的资源,进步程序的性能 ( 没有事件,就请休眠,不要功耗。有事件,就解决)
2、 RunLoop 外部实现逻辑?
- Core Foundation 中对于 RunLoop 的 5 个类:
CFRunLoopRef
CFRunLoopModeRef
CFRunLoopSourceRef
CFRunLoopTimerRef
CFRunLoopObserverRef
__CFRunLoop
的数据结构
struct __CFRunLoop { CFRuntimeBase _base; pthread_mutex_t _lock; /* locked for accessing mode list */ __CFPort _wakeUpPort; // used for CFRunLoopWakeUp Boolean _unused; volatile _per_run_data *_perRunData; // reset for runs of the run loop pthread_t _pthread; uint32_t _winthread; CFMutableSetRef _commonModes; CFMutableSetRef _commonModeItems; CFRunLoopModeRef _currentMode; // 这里有一个汇合 CFMutableSetRef _modes; struct _block_item *_blocks_head; struct _block_item *_blocks_tail; CFAbsoluteTime _runTime; CFAbsoluteTime _sleepTime; CFTypeRef _counterpart;};
3、 RunLoop 和线程的关系?
- 每条线程,都有惟一的一个,与之对应的 RunLoop 对象
runloops[thread] = runloop
- RunLoop 保留在一个全局的 Dictionary 里,线程作为 Key, RunLoop 作为 Value
- 线程刚创立时,并没有 RunLoop 对象, RunLoop 会在第一次获取它时,创立
- RunLoop 会在线程完结时,销毁
线程都没有了,runloop 也就没有意义了
子线程,要什么 runloop?没有 runloop , 就是命令行,调用一次就完结
有了 runloop, 能够重复休眠、唤醒、解决音讯
- 主线程的 RunLoop 曾经主动获取 ( 创立 ),子线程默认没有开启 RunLoop
子线程中,获取一下 currentRunLoop, 就创立开启了 RunLoop
CFRunLoopRef CFRunLoopGetCurrent(void) { CHECK_FOR_FORK(); CFRunLoopRef rl = (CFRunLoopRef)_CFGetTSD(__CFTSDKeyRunLoop); if (rl) return rl; // 从这里拿 return _CFRunLoopGet0(pthread_self());}
进入详情
// should only be called by Foundation// t==0 is a synonym for "main thread" that always worksCF_EXPORT CFRunLoopRef _CFRunLoopGet0(pthread_t t) { if (pthread_equal(t, kNilPthreadT)) { t = pthread_main_thread_np(); } __CFLock(&loopsLock); if (!__CFRunLoops) { __CFUnlock(&loopsLock); CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks); CFRunLoopRef mainLoop = __CFRunLoopCreate(pthread_main_thread_np()); CFDictionarySetValue(dict, pthreadPointer(pthread_main_thread_np()), mainLoop); if (!OSAtomicCompareAndSwapPtrBarrier(NULL, dict, (void * volatile *)&__CFRunLoops)) { CFRelease(dict); } CFRelease(mainLoop); __CFLock(&loopsLock); } CFRunLoopRef loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t)); __CFUnlock(&loopsLock); if (!loop) { CFRunLoopRef newLoop = __CFRunLoopCreate(t); __CFLock(&loopsLock); // 从字典外面,获取 runloop 对象 // __CFRunLoops 字典 // pthreadPointer(t) ,键 key loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t)); // runloop 对象 loop 不存在,就新建 if (!loop) { // 字典中,设置 // __CFRunLoops 字典 // pthreadPointer(t),键 key // newLoop, 值 value CFDictionarySetValue(__CFRunLoops, pthreadPointer(t), newLoop); loop = newLoop; } // don't release run loops inside the loopsLock, because CFRunLoopDeallocate may end up taking it __CFUnlock(&loopsLock); CFRelease(newLoop); } if (pthread_equal(t, pthread_self())) { _CFSetTSD(__CFTSDKeyRunLoop, (void *)loop, NULL); if (0 == _CFGetTSD(__CFTSDKeyRunLoopCntr)) { _CFSetTSD(__CFTSDKeyRunLoopCntr, (void *)(PTHREAD_DESTRUCTOR_ITERATIONS-1), (void (*)(void *))__CFFinalizeRunLoop); } } return loop;}
4、 timer 和 runloop 的关系?
5、 程序中增加每 3 秒响应一次的 NSTimer, 当拖动 tableView 时 timer 可能无奈响应,要怎么解决?
6、 RunLoop 是怎么响应用户操作的,具体流程是什么样的?
7、 说说 RunLoop 的几种状态
8、 runloop 的 mode 作用是什么?
应用的代码, 目前最新 1153