iOS学习笔记-134.RunLoop02——Runloop与线程
来源:互联网 发布:android studio 源码 编辑:程序博客网 时间:2024/05/21 22:52
- RunLoop02Runloop与线程
- 一通过 CFRunLoopc 的 _CFRunLoopGet0 函数 发现端倪
- 二Runloop与线程的关系
- 三代码示例
- 四运行结果
- 五结果分析
RunLoop02——Runloop与线程
一、通过 CFRunLoop.c 的 _CFRunLoopGet0 函数 发现端倪
我们首先下载到CFRunloop的源码
https://opensource.apple.com/source/CF/
找到我们 CFRunLoop.c 这个文件,搜索到 _CFRunLoopGet0 函数。
/获得runloop(创建runloop)// 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); // 创建主线程对应的runloop CFRunLoopRef mainLoop = __CFRunLoopCreate(pthread_main_thread_np()); // 使用字典保存主线程-主线程对应的runloop CFDictionarySetValue(dict, pthreadPointer(pthread_main_thread_np()), mainLoop); if (!OSAtomicCompareAndSwapPtrBarrier(NULL, dict, (void * volatile *)&__CFRunLoops)) { CFRelease(dict); } CFRelease(mainLoop); __CFLock(&loopsLock); } // 从字典中获取子线程的runloop CFRunLoopRef loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t)); __CFUnlock(&loopsLock); if (!loop) { // 如果子线程的runloop不存在,那么就为该线程创建一个对应的runloop CFRunLoopRef newLoop = __CFRunLoopCreate(t); __CFLock(&loopsLock); loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t)); // 把当前子线程和对应的runloop保存到字典中 if (!loop) { 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;}
我们可以看到,它会为线程创建一个 runloop 对象,然后存入到 字典中,这样它保持着一一对应的关系。
二、Runloop与线程的关系
1.Runloop和线程的关系:一个Runloop对应着一条唯一的线程。
Runloop对象是利用字典来进行存储,而且key是对应的线程Value为该线程对应的Runloop
问题:如何让子线程不死
回答:给这条子线程开启一个Runloop
2.Runloop的创建:主线程Runloop已经创建好了,子线程的runloop需要手动创建。
开一个子线程创建runloop,不是通过alloc init方法创建,而是直接通过调用
currentRunLoop 方法来创建,它本身是一个懒加载的
3.Runloop的生命周期:在第一次获取时创建,在线程结束时销毁
三、代码示例
//// ViewController.m// 03_UIView91_NSRunLoop简单运用//// Created by 杞文明 on 17/9/10.// Copyright © 2017年 杞文明. All rights reserved.//#import "ViewController.h"@interface ViewController ()@end@implementation ViewController-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ //====================Foundation============================ // 1.获取主线程对应的runloop NSRunLoop * mainRunLoop1 = [NSRunLoop mainRunLoop]; // 2.获取当前线程对应的runloop NSRunLoop * currentRunLoop1 = [NSRunLoop currentRunLoop]; NSLog(@"%@---------%@",mainRunLoop1,currentRunLoop1); //====================core foundation============================ // 1.获取主线程对应的runloop CFRunLoopRef mainRunLoop2 = CFRunLoopGetMain(); // 2.获取当前线程对应的runloop CFRunLoopRef currentRunLoop2 = CFRunLoopGetCurrent(); NSLog(@"%p---------%p",mainRunLoop2,currentRunLoop2); //Runloop和线程的关系 //一一对应,主线程的runloop已经创建,但是子线程的需要手动创建 [[[NSThread alloc]initWithTarget:self selector:@selector(run) object:nil] start];}//在runloop中有多个运行模式,但是runloop只能选择一种模式运行//mode里面至少要有一个timer或者是source-(void)run{ NSLog(@"=========run========"); //如何创建子线程对应的runLoop, currentRunLoop懒加载的 //现在还是不行的哦 NSLog(@"%@",[NSRunLoop currentRunLoop]); NSLog(@"run--%@",[NSThread currentThread]);}@end
四、运行结果
[20640:123485] <CFRunLoop 0x60000016a5c0 [0x103794df0]>......省略了很多输出......---------<CFRunLoop 0x60000016a5c0 [0x103794df0]>......省略了很多输出......[20640:123485] 0x60000016a5c0---------0x60000016a5c0[20640:123682] =========run========[20640:123682] <CFRunLoop 0x60000016b880 [0x103794df0]>{wakeup port = 0x110b, stopped = false, ignoreWakeUps = true, current mode = (none),common modes = <CFBasicHash 0x600000051850 [0x103794df0]>{type = mutable set, count = 1,entries => 2 : <CFString 0x10376c920 [0x103794df0]>{contents = "kCFRunLoopDefaultMode"}},common mode items = (null),modes = <CFBasicHash 0x600000051220 [0x103794df0]>{type = mutable set, count = 1,entries => 2 : <CFRunLoopMode 0x600000197830 [0x103794df0]>{name = kCFRunLoopDefaultMode, port set = 0xf07, queue = 0x60000016ba00, source = 0x6000001dfa40 (not fired), timer port = 0x650b, sources0 = (null), sources1 = (null), observers = (null), timers = (null), currently 526736125 (7463726825342) / soft deadline in: 1.84467366e+10 sec (@ -1) / hard deadline in: 1.84467366e+10 sec (@ -1)},}}[20640:123682] run--<NSThread: 0x600000269880>{number = 3, name = (null)}
五、结果分析
我们发现 在主线程中 通过 foundation 中
// 1.获取主线程对应的runloopNSRunLoop * mainRunLoop1 = [NSRunLoop mainRunLoop];// 2.获取当前线程对应的runloopNSRunLoop * currentRunLoop1 = [NSRunLoop currentRunLoop];
获取到的对象是同一个。
在主线程中 通过 core foundation 中
// 1.获取主线程对应的runloopCFRunLoopRef mainRunLoop2 = CFRunLoopGetMain();// 2.获取当前线程对应的runloopCFRunLoopRef currentRunLoop2 = CFRunLoopGetCurrent();
获取到的对象是同一个。
core foundation 和 foundation 获取到的对象不是同一个的。这是因为,NSRunLoop 是 对 CFRunLoop 的再次封装.
阅读全文
0 0
- iOS学习笔记-134.RunLoop02——Runloop与线程
- iOS学习笔记12—Runloop
- iOS学习笔记12—Runloop
- iOS学习笔记—Runloop 经典讲解
- iOS学习笔记12—Runloop
- iOS学习笔记-140.RunLoop08——Runloop应用之常驻线程
- iOS Runloop学习笔记
- iOS-RunLoop学习笔记
- iOS学习笔记-139.RunLoop07——Runloop处理流程
- iOS 学习笔记 --- RunLoop基础
- 《iOS开发笔记—运行循环RunLoop》
- iOS学习笔记-135.RunLoop03——Runloop相关类1_基础
- iOS学习笔记-136.RunLoop04——Runloop相关类2_CFRunLoopModeRef
- iOS学习笔记-138.RunLoop06——Runloop相关类4_ CFRunloopSourceRef和CFRunLoopObserverRef
- iOS RunLoop常驻线程
- iOS进阶必须学习的知识点之——Runloop
- iOS多线程——RunLoop与GCD、AutoreleasePool
- iOS RunLoop笔记
- jsp页面利用js动态显示当前系统时间
- leetcode 题目列表
- MicroStation V8i简体中文版中文字体乱码解决办法
- 使用自定义View直接显示今日头条头布局
- [对象]显示最新输入的新闻信息
- iOS学习笔记-134.RunLoop02——Runloop与线程
- fgthgffgjg吃的风格的风格
- number number number hdu 6189 矩阵快速幂
- 前端之常用库与框架
- 1072: 青蛙爬井
- sprigboot的配置文件
- 掉坑记录--two pointer
- equals与==背后的装箱拆箱机制
- Spark计算相关性系数(皮尔森、斯皮尔曼、卡方检验)