主线程
- 一个iOS程序执行后。默认会开启1条线程,称为“主线程”或“UI线程”(刷新UI界面最好在主线程中做。在子线程中可能会出现莫名其妙的BUG)
- 主线程的作用
- 显示\刷新UI界面
- 处理UI事件(比方点击事件、滚动事件、拖拽事件等)
- 注意点
- 别将比較耗时的操作放到主线程中
- 耗时操作会卡住主线程,严重影响UI的流畅度,给用户一种“卡”的坏体验
- iOS中多线程的实现方案
- pthread(c语言。程序猿管理)
- 一套通用的多线程API
- 适用于Unix\Linux\Windows等系统
- 跨平台\可移植
- 使用难度大
- NSThread(oc语言,程序猿管理)
- 使用更加面向对象
- 简单易用。可直接操作线程对象
- GCD(c语言,自己主动管理)
- 旨在替代NSThread等线程技术
- 充分利用设备的多核
- NSOperation(oc语言,自己主动管理)
- 基于GCD(底层是GCD)
- 比GCD多了一些更简单有用的功能
- 使用更加面向对象
- pthread(c语言。程序猿管理)
NSThread
- 一个NSThread对象就代表一条线程
- 创建、启动线程
- 常见相关使用方法
- 其它创建线程方式
- 长处:简单快捷
- 缺点:无法对线程进行更具体的设置
- 控制线程的状态
相互排斥锁
- 相互排斥锁使用格式
原子和非原子属性
- OC在定义属性时有nonatomic和atomic两种选择
- atomic:原子属性,为setter方法加锁(默认就是atomic)
- nonatomic:非原子属性。不会为setter方法加锁
- nonatomic和atomic对照
- atomic:线程安全,须要消耗大量的资源
- nonatomic:非线程安全。适合内存小的移动设备
- iOS开发的建议
- 全部属性都声明为nonatomic
- 尽量避免多线程抢夺同一块资源
- 尽量将加锁、资源抢夺的业务逻辑交给server端处理,减小移动client的压力
线程间的通信
- 什么叫做线程间通信
- 在1个进程中。线程往往不是孤立存在的。多个线程之间须要常常进行通信
- 线程间通信的体现
- 1个线程传递数据给另1个线程
- 在1个线程中运行完特定任务后,转到另1个线程继续运行任务
- 线程间通信经常用法
GCD
- 本质及长处
- 全称是Grand Central Dispatch,可译为“牛逼的中枢调度器”
- GCD会自己主动管理线程的生命周期(创建线程、调度任务、销毁线程)
- 程序猿仅仅须要告诉GCD想要运行什么任务,不须要编写不论什么线程管理代码
- 使用GCD的步骤
- 定制任务
- 确定想做的事情
- 将任务加入到队列中
- GCD会自己主动将队列中的任务取出,放到相应的线程中运行
- 任务的取出遵循队列的FIFO原则:先进先出,后进后出
- 定制任务
- 运行任务经常使用的函数
</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 用异步的方式运行任务</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">dispatch_async</span>(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">dispatch_queue_t</span> queue, dispatch_block_t block); dispatch_barrier_async(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">dispatch_queue_t</span> queue, dispatch_block_t block); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 在前面的任务运行结束后它才运行。并且它后面的任务等它运行完毕之后才会运行</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 注意:这个queue不能是全局的并发队列</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>
- 同步和异步的差别
- 同步:仅仅能在当前线程中运行任务。不具备开启新线程的能力
- 异步:能够在新的线程中运行任务,具备开启新线程的能力
- 队列的类型
- 并发队列(Concurrent Dispatch Queue)
- 能够让多个任务并发(同一时候)运行(自己主动开启多个线程同一时候运行任务)
- 并发功能仅仅有在异步(dispatch_async)函数下才有效
- 串行队列(Serial Dispatch Queue)
- 让任务一个接着一个地运行(一个任务运行完成后,再运行下一个任务)
- 并发队列(Concurrent Dispatch Queue)
- 并发队列
- 串行队列
- 线程间的通信
- 延迟操作
- iOS中延迟操作有3种
- 调用NSObject的方法
- 使用GCD函数
- 使用NSTimer
- iOS中延迟操作有3种
- 一次性代码
- 高速迭代
- 队列组
- 能够满足的一种需求(当然也能够用依赖线程依赖实现,下文会提到)
- 首先:分别异步运行2个耗时的操作
- 其次:等2个异步操作都运行完成后,再回到主线程运行操作
- 能够满足的一种需求(当然也能够用依赖线程依赖实现,下文会提到)
单例模式
- 单例模式的作用
- 能够保证在程序执行过程,一个类仅仅有一个实例,并且该实例易于供外界訪问
- 从而方便地控制了实例个数,并节约系统资源
- 单例模式的使用场合
- 在整个应用程序中,共享一份资源(这份资源仅仅须要创建初始化1次)
- 实现步骤:
NSOperation
- NSOperation和NSOperationQueue实现多线程的详细步骤
- 先将须要运行的操作封装到一个NSOperation对象中
- 然后将NSOperation对象加入到NSOperationQueue中
- 系统会自己主动将NSOperationQueue中的NSOperation取出来
- 将取出的NSOperation封装的操作放到一条新线程中运行
- NSOperation是抽象类,使用NSOperation子类的方式有3种
- NSInvocationOperation
- NSBlockOperation
- 自己定义子类继承NSOperation,实现内部对应的方法
- NSInvocationOperation
- NSBlockOperation
- NSOperationQueue
- 相关操作
- 操作依赖
- NSOperation之间能够设置依赖来保证运行顺序
- 能够在不同queue的NSOperation之间创建依赖关系
- 操作的监听
- 自己定义NSOperation
- 仅仅须要重写- (void)main方法。在里面实现想运行的任务
- 注意点
- 自己创建自己主动释放池(由于假设是异步操作,无法訪问主线程的自己主动释放池)
- 常常通过- (BOOL)isCancelled方法检測操作是否被取消,对取消做出响应
计算时间差
小结:
1、在GCD中,方法假设用异步函数能够开启子线程做事情。该方法中的程序会顺序运行究竟,然后再返回去开启子线程运行内部的操作。假设是同步函数。则不能开启子线程,里面的同步函数仅仅能一个一个运行下去。
2、假设在主队列中调用同步函数,easy造成死锁。
- 顶
- 0