IOS开发入门iOS多线程开发笔记
白羽 2019-05-21 来源 :网络 阅读 610 评论 0

摘要:本文将带你了解IOS开发入门iOS多线程开发笔记,希望本文对大家学IOS有所帮助。

    本文将带你了解IOS开发入门iOS多线程开发笔记,希望本文对大家学IOS有所帮助。


IOS开发入门iOS多线程开发笔记


基本概念、术语:
   进程(Precess):进程是操作系统管理和分配资源的最小单位,每个进程都有自己的内存空间、系统资源,至少有一个主线程和多个辅助线程。在iOS中,每个App运行的时候,都有对应的进程。  线程(Thread):线程则是操作系统具体的执行单元,代码的执行是在线程来完成的。在iOS中,线程的底层实现是基于POSIX thread  API的,也就是我们常说的pthread。 任务(Task):任务是我们抽象出来的需要执行的工作,一般指代一段代码。 同步 vs 异步
   同步是指函数的调用会阻塞当前的线程,必须等待函数返回才能继续执行接下来的代码。  异步函数的调用则不会阻塞当前线程,函数调用之后立刻返回,一般通过回调函数来处理函数的执行结果。  异步函数能够有效的完成一些耗时的任务,而不必影响代码的执行流,能够提高代码的处理效率。 串行 vs 并发
   串行指的是在同一个时间只能有一个任务在执行。 并发指的是在同一个时间可以有多个任务一起执行。  并发一般用于多核编程,通过高效的利用多核的优势,把不同的任务分配到各个执行单元来提高效率。 Dispatch Queue vs Operation  Queue
   GCD和NSOperation/NSOperationQueue是iOS上面来处理多线程开发的工具,对应的概念分别是Dispatch  Queue和Operation Queue。
   iOS并发编程模型
   在其他的操作系统中,我们往往需要手动创建线程、管理线程的生命周期,在不需要的时候负责销毁线程和线程使用的资源,更加痛苦的是需要使用线程锁、信号量、代码临界区等手段完成线程的同步工作,这些操作往往容易出错而且繁杂。  iOS通过抽象出队列的概念,让开发者更加关注于任务的安排和调度,而从线程的管理工作中解脱出来。在很多时候,iOS把一些繁杂且容易出错的工作(ARC代替MRC)抽离到底层中,能够让开发者把注意力更多地放到真正的任务上,这也是iOS能够吸引广大开发者的原因之一吧。
   NSThread vs GCD vs NSOperation,它们到底是什么?
   三种解决方案
   NSThread:一个封装pthread API的线程对象,需要进行线程创建、销毁和处理线程同步,是最接近系统底层的解决方案。  GCD:苹果基于C语言开发的,一个用于多核编程的解决方案,是一个轻量级的、以FIFO的顺序来执行并发任务的库。  NSOperation:建立在GCD的基础上,面向对象的解决方案,比GCD更加灵活,也更加强大。
   它们具体是什么?
   NSThread: Cocoa对于pthread  API的封装,提供了一套面向对象的接口,需要开发者自行管理线程的生命周期、处理线程同步。大多是的时候,我们是不需要直接使用这些底层的对象,而是使用GCD或者NSOperation等更加高级的接口。  关于Operation对象
   NSOperation对象本身是一个抽象类,不能直接使用。要么使用系统预定义的两个子类NSInvocationOperation和NSBlockOperation或者定义它的子类。  NSInvocationOperation:可以使用object和selector来创建一个NSInvocationOperation,非常的方便和灵活。当代码中已经有相关的处理逻辑方法时,建议直接使用NSInvocationOperation来进行替代。  NSBlockOperation:可以使用NSBlockOperation来并发的执行一个或者多个block,只有当所有的block都执行完毕,NSBlockOperation才算执行完成,有点像dispatch_group的概念。  所有的Operation都有下面的特性:
   支持在 operation 之间建立依赖关系,只有当一个 operation 所依赖的所有 operation 都执行完成时,这个 operation  才能开始执行; 支持一个可选的 completion block ,这个 block 将会在 operation  的主任务执行完成时被调用,在任务被取消的时候也会执行; 支持通过 KVO 来观察 operation  执行状态的变化,Operation正是通过KVO通知来实现依赖运行,所以我们需要在自定义的子类中的处理好KVO的属性; 支持设置执行的优先级,从而影响  operation 之间的相对执行顺序; 支持取消操作,可以允许我们停止正在执行的 operation 。 GCD队列:
   以FIFO顺序执行任务的队列调度系统,先入队列的任务一定先执行。 两种类型的队列:
   串行队列(Serial Queue):同一时间内只能有一个任务正在被执行。 并发队列(Concurrent  Queue):同一时间内可以有多个任务同时被执行。 iOS默认提供5个队列:
   主队列(Main Queue):应用程序主线程应用的队列,用于更新UI,属于串行队列。 四个全局队列:  按照队列优先级排序,分别是:High、Default、Low、Background。  这四个全局队列是由系统提供的,在所有的App中共享,当然也包含了Apple的应用。 并发队列中任务的执行顺序:  由于队列的并发数是有系统根据当前的资源动态管理的,我们不知道也不能够设置队列中任务执行的时机和所需时长。  只有当位于队列前面的任务执行完毕、出队列后,才会执行后面的任务,但是当前并发执行的任务数量我们不得而知。 自定义队列:
   我们可以自定义串行或者并发队列来完成任务的执行和调度。
   各自的优势和劣势
   优势:
   NSThread:
   能够执行实时任务。其他两者都是由系统管理的队列,不能保证实时性。 GCD:
   可以非常简洁的完成简单异步任务的调用,如在主线程更新UI,延迟执行。 只需要把任务分发到队列之后,不需要管理任务的调度情况。  NSOperation:
   给任务添加依赖 取消或者暂停一个正在执行的任务 有一个可选的completionBlock 可以通过KVO来查看任务的执行情况  可以给任务设置优先级,从而影响任务的执行顺序 短板:
   NSThread:需要进行线程的创建、销毁,以及处理线程同步的问题,过于繁杂,而且容易出错。 GCD:
   对于任务的管理不够:如不能取消任务、设置依赖和优先级等。 NSOperation:
   相比于GCD,会增加系统的额外开销。
   多线程代码中,需要注意哪些问题?
   有了GCD来调度block,我们为什么还需要NSBlockOperation?
   现有代码已经在使用OperationQueue,而我们不想使用Dispatch  Queue的时候,NSBlockOperation提供了一个面向对象的封装。 当我们需要dispatch  queue不能提供的功能时,如KVO观察Operation状态变化、设置operation之间依赖等。  NSInvocationOperation的灵活性是什么意思?
   我们可以通过上下文来改变selector和object对象。 如何定义一个非并发的operation?
   对于非并发的operation,我们只需要实现main方法和能够正常响应取消事件。  其他复杂的工作如KVO通知、依赖设置等工作NSOperation类的start方法已经帮我们提供了默认实现。 简单实现:
   提供一个自定义的初始化方法 重写main方法 如何实现一个并发的operation?
   一般我们不需要实现并发的operation,当operation和operation queue一起使用的时候,Operation  Queue会为非并发的operation创建单独的线程。  默认情况下,operation是同步执行的,也就是我们直接使用start方法的时候,它是在调用者的线程中执行的。  Operation的isConcurrent属性表明一个operation是否支持并发。  配置并发的Operation:只有当我们需要手动执行operation,并且希望支持并发执行,需要重写下面的方法。
   start:必须,配置任务执行的线程和其他资源,但是一定不能调用父类的实现。  main:可选,一般用来执行具体的任务,而start方法更多是用来配置初始环境,当然也可以用来执行具体的任务。  isExecuting和isFinished:必须,并发的Operation需要自己来配置环境,同时还需要向外界来传递状态的变化,而isExecuting和isFinished这两个状态的变化需要使用KVO来通知外部。  isConcurrent:必须,用来标识一个Operation是否支持并发。 如何完成自定义operation的cancel操作?
   在下面这几个关键点的检查isCancelled属性
   在真正开始执行operaiton之前 至少在一次循环之中需要检查一次,如果单次循环耗时较长,则需要更加频繁的检查  在任何相对比较容易终止Operation的地方  需要注意的是虽然Operation支持取消操作,但是并不是立刻就可以被终止的,而是在下一个isCancelled的检查点。  在我们自定义Operation子类的时候,即使operation是被cancel了,我们仍然需要设置isFinished方法为true,因为在设置operation依赖的时候,它们的operation就是通过KVO来观察isFinished方法来判断时候可以执行的,如果在cancel的时候,没有设置isFinished方法,那么其他的operation将永远不会执行。  如何定制Operation对象的执行行为:
   在Operation添加到Operation Queue之前,我们可以配置Operation的一些行为。 配置依赖关系
   依赖关系是在Operation之间的,与是否在同一个Operation Queue没有关系,也就是说,我们在位于不同的Operation  Queue中的Operation之间设置依赖。 注意不要产生依赖循环。 在把operation添加到Operation  Queue之前就需要配置好依赖,在添加后设置的依赖可能无效。 修改operation在队列中的优先级
   Operation在队列中的执行顺序取决于isReady状态和队列优先级。 isReady受它所依赖的operation状态的影响,只有当依赖的所有operation都变为isFinished的时候,isReady状态才为true。  queuePriority只能作用与相同队列中的operation,并且队列优先级只有当isReady为true的时候,才会决定operation的执行顺序。  isReady为FALSE的时候,isReady为true的低队列优先级的operation也会先执行。 一个串行的 operation queue  与一个串行的 dispatch queue是一样的么?
   两者都是在同一时间内只能有一个任务被执行,但是在任务的执行顺序上是不同的:
   dispatch queue 的执行顺序一直是 FIFO 的 operation  queue中的operation执行的顺序取决于isReady和queuePriority状态。 如何用GCD实现一个线程安全的单例?
 

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之IOS频道!

本文由 @白羽 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程