多线程和runloop
2017-09-02 本文已影响18人
b470b9fc7145
1.主线程的runLoop是一直在运行的
2.其他线程的runLoop需要手动开启,但是不能自己创建
3.苹果不允许直接创建 RunLoop,它只提供了两个自动获取的函数:CFRunLoopGetMain() 和 CFRunLoopGetCurrent()
4.一个线程执行完会自动销毁的,里面创建的runLoop也跟着销毁了
5.FDTemplateLayoutCell只是在空闲的时候去缓存计算cell的高度(主线程,不用担心线程执行完关闭的问题/ observer计算完了进行了手动移除)
6.AFN是采用后台的线程中开启runloop;至于后台线程是否一直存在,这个需要再看下源码
7.如果手动创建线程(貌似只能用NSThread,其他的不能手动创建),需要自己手动释放.
RunLoop与线程
- 每条线程都有唯一的一个与之对应的RunLoop对象
- 主线程的RunLoop(直接在 main函数里加)已经自动创建好了,子线程的RunLoop需要主动创建
- RunLoop在第一次获取时创建,在线程结束时销毁
获得RunLoop对象
- Foundation
- [NSRunLoop currentRunLoop]; // 获得当前线程的RunLoop对象
- [NSRunLoop mainRunLoop]; // 获得主线程的RunLoop对象
- Core Foundation
- CFRunLoopGetCurrent(); // 获得当前线程的RunLoop对象
- CFRunLoopGetMain(); // 获得主线程的RunLoop对象
RunLoop相关类
- Core Foundation中关于RunLoop的5个类
- CFRunLoopRef//要监听的对象
- CFRunLoopModeRef
- CFRunLoopSourceRef
- CFRunLoopTimerRef
- CFRunLoopObserverRef
多线程
- 全局队列为系统创建,不需要自己创建,拿过来就用,用着方便并行队列和全局队列执行效果相同
- 全局队列没有名称,调试时,无法确认准确队列
- 每一个应用程序都只有一个主线程
- iOS开发中所有UI更新工作都必须在主线程上执行,因为线程安全需要消耗性能,苹果为了保留性能优势所以放弃了线程安全 ,所以改UI都要在主线程上.
- 异步任务任务在主线程上是保持队形的,也就是异步是在主线程6. 一个线程上执行的主线程不可以执行同步任务,因为同步任务是要等到上一个线程结束后才会执行,但是主线程一直不会停止当前的任务,所以它不会去执行一个同步任务
- 无论什么队列和什么任务,线程的创建和回收不需要程序员参与,线程的创建和回收工作是由队列负责的
GCD
- 所有开线程的前提是,有任务加到队列中
- sync 同步函数不会开线程
- async 异步函数会开线程
- 有了线程,才存在runLoop这个东西
NSOperationQueue
- 默认情况下,调用了start方法后并不会开一条新线程去执行操作,而是在当前线程同步执行操作-----在 main线程中
- 只有将NSOperation放到一个NSOperationQueue中,才会异步执行操作--在子线程中
三种多线程技术的对比
-
NSThread:
- 优点:NSThread 比其他两个轻量级,使用简单
- 缺点:需要自己管理线程的生命周期、线程同步、加锁、睡眠以及唤醒等。线程同步对数据的加锁会有一定的系统开销(需要自己想AFN一样使用autoreleasepool)
-
NSOperation:
- 不需要关心线程管理,数据同步的事情,可以把精力放在自己需要执行的操作上
- NSOperation是面向对象的
-
GCD:
- Grand Central Dispatch是由苹果开发的一个多核编程的解决方案。iOS4.0+才能使用,是替代NSThread, NSOperation的高效和强大的技术
- GCD是基于C语言的
- GCD是一个苹果公司用C语言开发的框架,好在iOS6.0以后,GCD对象被纳入了ARC的管理范围,因此不再需要手动管理GCD的内存了。如果你的工程部署的最低目标低于iOS6.0或者Mac OSX 10.8,则需要手动管理GCD内存。
总结
任务加到队列--->队列(同步/异步)-->开启线程-->线程执行-->线程执行完任务自动关闭线程