深入浅出 RunLoop(四):RunLoop 与线程
2020/2/28 23:15:26
本文主要是介绍深入浅出 RunLoop(四):RunLoop 与线程,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
RunLoop 系列文章
深入浅出 RunLoop(一):初识
深入浅出 RunLoop(二):数据结构
深入浅出 RunLoop(三):事件循环机制
深入浅出 RunLoop(四):RunLoop 与线程
深入浅出 RunLoop(五):RunLoop 与 NSTimer
深入浅出 RunLoop(六):相关面试题
RunLoop 与线程的关系
苹果官方文档中,RunLoop
的相关介绍写在线程编程指南中,可见RunLoop
和线程的关系不一般。Threading Programming Guide(苹果官方文档)
RunLoop
对象和线程是一一对应关系;RunLoop
保存在一个全局的Dictionary
里,线程作为key
,RunLoop
作为value
;RunLoop
创建时机:线程刚创建时并没有RunLoop
对象,RunLoop
会在第一次获取它时创建(获取方式已经在《深入浅出 RunLoop(一):初识》文章中讲到);RunLoop
销毁时机:RunLoop
会在线程结束时销毁;- 主线程的
RunLoop
已经自动获取(创建),子线程默认没有开启RunLoop
; - 主线程的
RunLoop
对象是在UIApplicationMain
中通过[NSRunLoop currentRunLoop]
获取,一旦发现它不存在,就会创建RunLoop
对象。
开启子线程的 RunLoop 的过程
获取 RunLoop 对象
可以通过以下方式来获取RunLoop
对象:
// Foundation [NSRunLoop mainRunLoop]; // 获取主线程的 RunLoop 对象 [NSRunLoop currentRunLoop]; // 获取当前线程的 RunLoop 对象 // Core Foundation CFRunLoopGetMain(); // 获取主线程的 RunLoop 对象 CFRunLoopGetCurrent(); // 获取当前线程的 RunLoop 对象 复制代码
我们来看一下CFRunLoopGetCurrent()
函数是怎么获取RunLoop
对象的:
CFRunLoopRef CFRunLoopGetCurrent(void) { CHECK_FOR_FORK(); CFRunLoopRef rl = (CFRunLoopRef)_CFGetTSD(__CFTSDKeyRunLoop); if (rl) return rl; return _CFRunLoopGet0(pthread_self()); // 调用 _CFRunLoopGet0 函数并传入当前线程 } 复制代码
// should only be called by Foundation // t==0 is a synonym for "main thread" that always works CF_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); } // ️当前线程作为 Key,从 __CFRunLoops 字典中获取 RunLoop CFRunLoopRef loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t)); __CFUnlock(&loopsLock); if (!loop) { // ️如果字典中不存在 CFRunLoopRef newLoop = __CFRunLoopCreate(t); // 创建当前线程的 RunLoop __CFLock(&loopsLock); loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t)); if (!loop) { CFDictionarySetValue(__CFRunLoops, pthreadPointer(t), newLoop); // 保存到字典中 loop = newLoop; } // don't release run loops inside the loopsLock, because CFRunLoopDe
这篇关于深入浅出 RunLoop(四):RunLoop 与线程的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2022-10-05Swift语法学习--基于协议进行网络请求
- 2022-08-17Apple开发_Swift语言地标注释
- 2022-07-24Swift 初见
- 2022-05-22SwiftUI App 支持多语种 All In One
- 2022-05-10SwiftUI 组件参数简写 All In One
- 2022-04-14SwiftUI 学习笔记
- 2022-02-23Swift 文件夹和文件操作
- 2022-02-17Swift中使用KVO
- 2022-02-08Swift 汇编 String array
- 2022-01-30SwiftUI3.0页面反向传值