iOS多线程-概念
线程概述
有些程序是一条直线,起点到终点;有些程序是一个圆,不断循环,直到将它切断
一个运行着的程序就是一个进程或者叫做一个任务,一个进程至少包含一个线程,线程就是程序的执行流。Mac和iOS中的程序启动,创建好一个进程的同时, 一个线程便开始运行,这个线程叫主线程。主线程在程序中的地位和其他线程不同,它是其他线程最终的父线程,且所有界面的显示操作即AppKit或 UIKit的操作必须在主线程进行。
系统中的每一个进程都有自己独立的虚拟内存空间,而同一个进程中的多个线程则共用进程的内存空间。每创建一个新的线程,都需要一些内存(如每个线程有自己的Stack空间)和消耗一定的CPU时间。另外当多个线程对同一个资源出现争夺的时候需要注意线程安全问题
多线程的实现原理:虽然在同一时刻,CPU只能处理1条线程,但是CPU可以快速地在多条线程之间调度(切换),造成了多线程并发执行的假象。
多线程的优点
能适当提高程序的执行效率。
能适当提高资源利用率(CPU、内存利用率)。
多线程的缺点
创建线程是需要成本的:iOS下主要成本包括:在栈空间的子线程512KB、主线程1MB,创建线程大约需要90毫秒的创建时间。
线程越多,CPU在调度线程上的开销就越大。
线程越多,程序设计就越复杂:因为要考虑到线程之间的通信,多线程的数据共享。
计算机操作系统都有的基本概念,以下概念简单方式来描述。
- 进程: 一个具有一定独立功能的程序关于某个数据集合的一次运行活动。可以理解成一个运行中的应用程序。
- 线程: 程序执行流的最小单元,线程是进程中的一个实体。
- 同步: 只能在当前线程按先后顺序依次执行,不开启新线程。
- 异步: 可以在当前线程开启多个新线程执行,可不按顺序执行。
- 队列(Dispatch Queue): 装载线程任务的队形结构。
- 并行队列(Concurrent Dispatch Queue): 线程执行可以同时一起进行执行,不需要上一个执行完,就能执行下一个的。
- 串行队列(Serial Dispatch Queue): 线程执行只能依次逐一先后有序的执行,等待上一个执行完,再执行下一个。
注意:
- 一个进程可有多个线程。
- 一个进程可有多个队列。
- 队列可分并发队列和串行队列。
iOS开发中的多线程
iOS的主线程
一个iOS程序运行后,默认会开启1条线程,称为“主线程”或“UI线程”
主线程的作用:
- 显示\刷新UI界面
- 处理UI事件(比如点击事件、滚动事件、拖拽事件等)
主线程的使用注意事项:
不能把比较耗时的操作放到主线程中,,严重影响UI的流畅度,给用户一种程序“卡顿”的体验。
因此,要将耗时的操作放在子线程中异步执行。这样一来,及时开始执行了耗时的操作,也不会影响主线程中UI交互的体验。
iOS的子线程
子线程是异步执行的,不影响主线程。在iOS开发中,我们需要将耗时的任务(网络请求,复杂的运算)放在子线程进行,不让其影响UI的交互体验。
多线程安全
当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题。就好比好几个人在同时修改同一个表格,造成数据的错乱。
资源抢夺的解决方案
我们需要给数据添加互斥锁。也就是说,当某线程访问一个数据之前就要给数据加锁,让其不被其他的线程所修改。就好比一个人修改表格的时候给表格设置了密码,那么其他人就无法访问文件了。当他修改文件之后,再讲密码撤销,第二个人就可以访问该文件了。
注意:
这里的线程都为子线程,如果给数据加了锁,就等于将这些异步的子线程变成同步的了,这也叫做线程同步技术。
互斥锁使用:
@synchronized(锁对象) { // 需要锁定的代码 };
互斥锁的优缺点
优点:能有效防止因多线程抢夺资源造成的数据安全问题
缺点:需要消耗大量的CPU资源
互斥锁的使用前提:多条线程抢夺同一块资源的时候使用。
互斥锁在iOS开发中的使用
OC在定义属性时有nonatomic和atomic两种选择
atomic:原子属性,为setter方法加锁(默认就是atomic)
nonatomic:非原子属性,不会为setter方法加锁
nonatomic和atomic对比
atomic:线程安全,需要消耗大量的资源
nonatomic:非线程安全,适合内存小的移动设备
建议:
所有属性都声明为nonatomic,尽量避免多线程抢夺同一块资源,将加锁、资源抢夺的业务逻辑交给服务器端处理,减小移动客户端的压力。
iOS多线程技术对比
NSThread
每个NSThread对象对应一个线程,真正最原始的线程。
1)优点:NSThread 轻量级最低,相对简单。
2)缺点:手动管理所有的线程活动,如生命周期、线程同步、睡眠等。
NSOperation
自带线程管理的抽象类。
1)优点:自带线程周期管理,操作上可更注重自己逻辑。
2)缺点:面向对象的抽象类,只能实现它或者使用它定义好的两个子类:NSInvocationOperation 和 NSBlockOperation。
GCD
Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法。
1)优点:最高效,避开并发陷阱。
2)缺点:基于C实现。
选择小结
1)简单而安全的选择NSOperation实现多线程即可。
2)处理大量并发数据,又追求性能效率的选择GCD。
3)NSThread本人选择基本上是在做些小测试上使用,当然也可以基于此造个轮子。
场景选择
图片异步加载。这种常见的场景是最常见也是必不可少的。异步加载图片有分成两种来说明一下。
第一种,在UI主线程开启新线程按顺序加载图片,加载完成刷新UI。
第二种,依然是在主线程开启新线程,顺序不定地加载图片,加载完成个字刷新UI。
创作工具上的异步。 这个跟上边任务调度道理差不多,只是为了丰富描述,有助于“举一反三”效果。如下描述的是app创作小说。
场景一,app本地创作10个章节内容未成同步服务器,接着同时发表这10个章节将产生的一系列动作,其中上传内容,获取分配章节Id,如果后台没有做处理最好方式做异步按顺序执行。
场景二,app本地创作列表中有3本小说要发表,如果同时发表创作列表中的3本小说,自然考虑并行队列执行发表。
声明:本文非原创,仅仅整理一些开发技能知识文章,以作存档学习用
参考
http://www.jianshu.com/p/6e6f4e005a0b
http://www.jianshu.com/p/f28a50f72bb1
http://www.jianshu.com/p/6e74f5438f2c
https://juejin.im/post/57cb8e8367f3560057bf4da1
http://mobile.51cto.com/iphone-403490.htm