您的位置:首页 > 移动开发 > IOS开发

iOS开发:多线程总结

2016-04-01 13:34 302 查看
一、进程与线程?

进程简单的说就是一个程序。进程有独立的地址空间,一个进程崩溃后,不会对其它进程产生影响。
线程只是一个进程中的不同执行路径,线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉。

简而言之,一个程序就是一个进程,而一个程序中的多个任务则被称为线程。

进程是系统进行资源分配和调度的一个独立单位.线程是进程的一个实体,是CPU调度和分派的基本单位

多线程的用处:增加运行效率、防止主线程堵塞、要求并发操作时。

二、实现多线程的方法

方法一:pThread

方法二:NSThread 有三种创建线程的方法 alloc方法(需要启动) detach方法 perform方法。多线程中执行的任务是放在方法里的。

方法三:GCD

GCD介绍:

中枢调度器,替代诸如NSThread等技术的很高效和强大的技术,是为多核的并行提出的解决方案。

GCD优点:

会自动利用更多的CPU内核 单核 双核 多核 都适用

自动管理线程不需要程序员操心(包括线程的创建、销毁、调度、线程安全、资源泄露等问题)。

程序员只需要告诉GCD执行什么任务即可。
GCD使用:

1.先创建一个队列:串行队列(一个任务执行完了才能取出下个任务) 并发队列(可以取出多个任务只要有线程去执行)之分。

2.创建任意个任务:同步任务(在当前线程执行没有开新线程,且同步执行立马执行) 异步任务(至少开一个新线程,不需要立马执行先放到队列里)。任务:GCD里的任务是block代码块。

串行同步:顺序执行 执行在当前线程立马执行

串行异步:顺序执行 执行在新线程可先放到队列里

并发同步:顺序执行 执行在当前线程(有并发执行的能力,只不过是没有线程条件允许)

并发异步:并发执行 执行在多个子线程里,且多个任务是并发执行。同步任务的作用:比如小说网站
需要先登录才能 下载a小说 下载b小说(这个登录任务就需要用到同步,目的是只有登录了才能下载)

3.将任务添加到队列里。

全局队列:本质是并发队列。 与并发队列的区别是所有的应用程序共享,在(MRC)也不需要程序员管理和释放,两个参数:第一个参数填0 适配ios7之后的系统都可用 第二个参数:0 预留参数。

主队列异步:把任务放到主队列里不需要立马执行(因为主队列当前肯定有任务在执行)

主队列同步:把任务放到主队列里 需要立马执行(会死锁)

GCD其它使用:

GCD还有一个延迟操作。

线程组的概念:将所有的线程放到线程组,目的是监听组内的线程是否结束

一次性执行代码。

GCD队列选择:

串行异步:执行效率低 占用资源少省电 使用手机网络时使用

并行异步:执行效率高 占用资源多费电 使用WiFi 对执行顺序没有要求

并行同步:阻塞后续程序 其实就是一种依赖关系。

线程通讯:

更新UI必须回到主线程。(保证线程安全的一种方式 另外一种方式是添加线程锁:互斥锁,NSLock)

方法四:NSOperation

NSOperation介绍:
NSOperation是用oc的方式封装GCD里面的全局队列的操作封装的就是异步执行方法。所以NSOperation是全局队列异步执行方式。

NSOperation最大并发数:
最大并发数,不是线程的数量,而是同时执行的操作数量。

NSOperation挂起(就是线程的暂停和继续):

挂起的是队列不会影响已经在执行的操作。
NSOperation可以查看还在队列里的操作数量

NSOperation的取消:
注意:只要是取消了队列,我们就要把队列处于启动状态,以便队列的继续。

NSOperation的依赖关系:

注意:避免出现循环依赖的情况出现

三、GCD与NSOperation的区别

由于NSOperation是对GCD全局队列的封装就有局限性,无法做到一次性执行,延迟操作 调度组

但NSOperation也有一些自己的方法是GCD无法做到的比如依赖关系、队列的挂起和取消。

四、关于线程安全的问题

主要是避免在同一时刻多线程访问同一个数据(包括读取和写入,最主要的是不能同时写入)

解决方法:

在主线程更新ui

添加线程锁,一般是添加互斥锁原理是线程同步技术。

加锁一般三种:

//1互斥锁
@synchronized(对象或类名){

执⾏行代码

}

@synchronized(self){

}

//2NSLock

NSLock *TheLock = [[NSLock alloc] init];

[TheLock lock];
[TheLock unlock];

//线程等待,线程顺序执行,可以发送信号方式在一个线程唤醒另一个线程等待

[ALock signal]; //一个线程
[ALock wait]; //另一个线程

设置线程的优先级

采用原子操作

使用GCD的一次性执行代码

使用模型赋值也能保证线程安全

注意block的使用问题

五、线程、runloop、有什么关系?

1.Runloop寄生于线程:一个线程只能有唯一对应的runloop;但这个根runloop里可以嵌套子runloops;runloop是线程的基础架构。每个线程,包括程序的主线程(main
thread)都有与之相应的run loop对象.主线程的runloop默认是启动的。对其它线程来说,run
loop默认是没有启动的,如果你需要更多的线程交互则可以手动配置和启动.可以通过NSRunLoop的
currentRunLoop
类方法来获取当前线程的runloop

2.自动释放池寄生于Runloop:程序启动后,主线程注册了两个Observer监听runloop的进出与睡觉。

一个最高优先级OB监听Entry状态,一个最低优先级OB监听BeforeWaiting状态和Exit状态。

线程(创建)-->runloop将进入-->最高优先级OB创建释放池-->runloop将睡-->最低优先级OB销毁旧池创建新池-->runloop将退出-->最低优先级OB销毁新池-->线程(销毁)

1- Entry:通知OB(创建pool);

2- 执行阶段:按顺序通知OB并执行timer,source0;若有source1执行source1;

3- 休眠阶段:利用mach_msg判断进入休眠,通知OB(pool的销毁重建);被消息唤醒通知OB;

4- 执行阶段:按消息类型处理事件;

5- 判断退出条件:如果符合退出条件(一次性执行,超时,强制停止,modeItem为空)则退出,否则回到第2阶段;

6- Exit:通知OB(销毁pool)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: