多线程常见的面试题:
1、你对多线程的理解?
2、iOS多线程的方案有哪几种?你更倾向于哪一种?
3、NSOperationQueue 和 GCD 的区别,以及各自的优势
4、线程安全的处理手段有哪些?
5、主队列中添加任务会发生什么?
带着这些问题我们来系统的看一下多线程的问题,为了方便以后的学习查阅,便有了这篇文章,首先我们来了解下几个基本的概念:
1、线程和进程
进程:进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
简单来说,进程是指在系统中正在运行的一个应用程序,每一个程序都是一个进程,并且进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内。
线程:线程是程序执行流的最小单元,线程是程序中一个单一的顺序控制流程。是进程内一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指运行中的程序的调度单位。
对比理解:进程是系统资源分配的最小单位,线程是任务执行的最小单位,线程并不单独占有内存空间,同一进程中的不同不同线程共享进程的内存空间,一个个进程要想执行任务,必须得有线程。
简单来说:线程中的任务是串行执行的,要在一个线程中执行多个任务,只能一个一个的顺序执行,也就是在同一时间一个线程只能执行一个任务。
2、同步 异步 并发 串行
同步和异步主要影响:能不能开启新线程
同步:在当前线程中执行,不具备开启新线程的能力。
异步:在新的线程中执行,具备开启新线程的能力。并发和串行主要影响:任务的执行方式
并发:多个任务并发(同时)执行。
串行:一个任务执行完毕后,在执行下一个任务。
3、多线程
多线程(multithreading),是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能。
- 原理
- 同一时间,CPU只能处理1条线程,只有1条线程在工作(执行)
多线程并发(同时)执行,其实是CPU快速地在多条线程之间调度(切换)。 - 如果CPU调度线程的时间足够快,就造成了多线程并发执行的假象
- 注意:多线程并发,并不是cpu在同一时刻同时执行多个任务,只是CPU调度足够快,造成的假象。
- 优点
- 能适当提高程序的执行效率。
- 能适当提高资源利用率(CPU、内存利用率)。
- 缺点
- 开启线程需要占用一定的内存空间(默认情况下,主线程占用1M,子线程占用512KB),如果开启大量的线程,会占用大量的内存空间,降低程序的性能。
- 程越多,CPU在调度线程上的开销就越大。
4、主线程
一个iOS程序运行后,默认会开启1条线程,称为“主线程”或“UI线程”。
- 作用
- 刷新UI界面
- 处理UI事件(比如点击事件、滚动事件、拖拽事件等)
- 注意
- 刷新UI必须放在主线程
- 别将比较耗时的操作放到主线程中
- 耗时操作会卡住主线程,严重影响UI的流畅度
5、NSThread GCD NSOperation
1. NSThread
NSThreads是封装最小最轻量级的,使用更灵活,但是需要手动管理线程的生命周期、线程同步和线程加锁,开销较大;
NSThread的基本使用比较简单,可以动态创建初始化NSThread对象,对其进行设置然后启动;也可以通过NSThread的静态方法快速创建并启动新线程;此外NSObject基类对象还提供了隐式快速创建NSThread线程的performSelector系列类别扩展工具方法;NSThread还提供了一些静态工具接口来控制当前线程以及获取当前线程的一些信息。
2.GCD(大中央调度)
GCD(Grand Central Dispatch),又叫大中央调度,对线程操作进行了封装,加入了很多新的特性,内部进行了效率优化,提供了简洁的C语言接口,使用更加简单高效,也是苹果推荐的方式。
对于GCD多线程编程的理解需要结合实例和实践去体会、总结,网上有一篇国外的GCD详细教程,结合案例通俗易懂,可以帮助快速掌握,文章地址为:(https://www.raywenderlich.com/60749/grand-central-dispatch-in-depth-part-1),另外国内有业界人士对其做了翻译,中文版地址为:(https://github.com/nixzhu/dev-blog/blob/master/2014-04-19-grand-central-dispatch-in-depth-part-1.md),教程分两部分,此处给出第一部分地址,第二部分可因此找到。这里对其进行进一步的总结提炼,整理出如下必会内容,帮助快速掌握使用:
同步dispatch_sync与异步dispatch_async任务派发
串行队列与并发队列dispatch_queue_t
dispatch_once_t只执行一次
dispatch_after延后执行
dispatch_group_t组调度
3.NSOperation
NSOperation是基于GCD的一个抽象基类,将线程封装成要执行的操作,不需要管理线程的生命周期和同步,但比GCD可控性更强,例如可以加入操作依赖(addDependency)、设置操作队列最大可并发执行的操作个数(setMaxConcurrentOperationCount)、取消操作(cancel)等。NSOperation作为抽象基类不具备封装我们的操作的功能,需要使用两个它的实体子类:NSBlockOperation和NSInvocationOperation,或者继承NSOperation自定义子类。
NSBlockOperation和NSInvocationOperation用法的主要区别是:前者执行指定的方法,后者执行代码块,相对来说后者更加灵活易用。NSOperation操作配置完成后便可调用start函数在当前线程执行,如果要异步执行避免阻塞当前线程则可以加入NSOperationQueue中异步执行。