Apple开发_GCD简介
1、GCD简介
-
GCD 是 Grand Central Dispatch(译为 “中枢调度器”)的简称,它是基于 C 语言编写的,是苹果公司为多核的并行运算提出的解决方案。
-
GCD 在工作时会自动利用更多的处理器核心,以充分利用更强大的机器。
-
如果使用 GCD,完全由系统管理线程,我们不需要编写线程代码,只需定义想要执行的任务,然后添加到适当的调度队列(dispatch queue),GCD 会负责创建线程和调度你的任务。
-
它首次发布在 Mac OS X 10.6 ,iOS 4 上。在 iOS 所有实现多线程的方案中,GCD 应该是最有魅力的,GCD 是一个替代诸如 NSThread, NSOperationQueue,NSInvocationOperation 等技术的很高效和强大的技术。
-
1.1 工作原理:
- 将长期运行的任务拆分成多个工作单元,并将这些单元添加到 dispath queue 中,系统会为我们管理这些 dispath queue,根据可用的处理资源,安排他们在任何可用的处理器核心上执行任务。
- 我们不需要直接启动和管理后台线程。
- 一个任务可以是一个函数(function)或者是一个 block。
- GCD 的底层依然是用线程实现,不过这样可以让程序员不用关注实现的细节。
- 将任务添加到队列,并且指定执行任务的函数,执行任务。任务使用 block 封装,任务的 block 没有参数也没有返回值。
-
1.2 执行任务的函数:
- 异步 dispatch_async
- 不用等待当前语句执行完毕,就可以执行下一条语句。
- 会开启线程执行 block 的任务。
- 异步是多线程的代名词。
- 同步 dispatch_sync
- 必须等待当前语句执行完毕,才会执行下一条语句。
- 不会开启线程。
- 在当前线程执行 block 的任务。
- 同步任务的作用:同步任务,可以让其他异步执行的任务,"依赖" 某一个同步任务。例如:在用户登录之后,再异步下载文件!
- 异步 dispatch_async
-
1.3 任务调度队列:
- GCD 中的 FIFO 队列称为 dispatch queue(调度队列)。系统提供了许多预定义的 dispatch queue,包括可以保证始终在主线程上执行工作的 dispatch queue。
- 也可以创建自己的 dispatch queue,而且可以创建任意多个。GCD 的 dispatch queue 严格遵循 FIFO(先进先出) 原则,添加到 dispatch queue 的工作单元将始终按照加入 dispatch queue 的顺序启动。
- dispatch queue 按先进先出的顺序,串行或并发地调度任务在线程上实行。
- dispatch queue 分为下面三种:
-
Serial:
- 串行队列,又称为 private dispatch queues,一次只能 "调度" 一个任务, 当前任务完成才开始出列并启动下一个任务。Serial queue 通常用于同步访问特定的资源或数据。当你创建多个 Serial queue 时,虽然它们各自是同步执行的,但 Serial queue 与 Serial queue 之间是并发执行的。
-
Concurrent:
- 并发队列,又称为 global dispatch queues,一次可以 "调度" 多个任务,尽可能多地启动任务并发执行,任务执行完成的顺序是随机的。
- 系统给每一个应用程序提供了三个 concurrent dispatch queues。这三个并发调度队列是全局的,它们只有优先级的不同。因为是全局的,我们不需要去创建。我们只需要通过使用函数 dispath_get_global_queue 去得到队列。
-
Main dispatch queue:
- 主队列,它是全局可用的 serial queue,专门用来在主线程上调度任务的队列。不会开启线程,主队列异步执行时如果主线程上正在有代码执行,就不会调度队列中的任务,等待主线程空闲之后再调度任务。主线程中主队列同步执行时,主队列和主线程相互等待会造成死锁。
-
-
1.4 各种队列的执行效果:
Type 全局并发队列 手动创建串行队列 主队列 同步 (sync) 没有开启新线程 没有开启新线程 没有开启新线程 ~ 串行执行任务 串行执行任务 串行执行任务 异步 (async) 有开启新线程 有开启新线程 没有开启新线程 ~ 并发执行任务 串行执行任务 串行执行任务 - 开不开线程由执行任务的函数决定:
- 异步开,异步是多线程的代名词。
- 同步不开。
- 开几条线程由队列决定:
- 串行队列开一条线程。
- 并发队列开多条线程。
- 主队列不会开启线程。
- 开不开线程由执行任务的函数决定:
-
1.5 队列的选择:
- 多线程的目的:将耗时的操作放在后台执行!
- 串行队列,只开一条线程,所有任务顺序执行
- 如果任务有先后执行顺序的要求。
- 效率低 -> 执行慢 -> "省电"。
- 有的时候,用户其实不希望太快!例如使用 3G 流量,"省钱"。
- 并发队列,会开启多条线程,所有任务不按照顺序执行
- 如果任务没有先后执行顺序的要求。
- 效率高 -> 执行快 -> "费电"。
- WIFI,包月。
- 实际开发中
- WIFI 线程数 6 条。
- 3G / 4G 移动开发的时候,2~3 条,再多会费电费钱。
-
1.6 全局队列 & 并发队列的区别:
-
1)全局队列:
- 没有名称。
- 无论 MRC & ARC 都不需要考虑释放。
- 日常开发中,建议使用 "全局队列"。
-
2)并发队列:
- 有名字,和 NSThread 的 name 属性作用类似。
- 如果在 MRC 开发时,需要使用 dispatch_release(q); 释放相应的对象。
- 开发第三方框架时,建议使用并发队列。
-
-
1.7 GCD & NSThread 对比:
- GCD 所有的代码写在一起的,让代码更加简单,易于阅读和维护。
- NSThread 通过 @selector 指定要执行的方法,代码分散。
- GCD 通过 block 指定要执行的代码,代码集中。
- 使用 GCD 不需要管理线程的创建/销毁/复用的过程。程序员不用关心线程的生命周期。
- NSThread 需要自己创建线程对象,并且指定 selector 方法,然后 start。
- GCD 只需要将任务添加给队列,并且指定执行的函数
- 如果要开多个线程 NSThread 必须实例化多个线程对象。
- NSThread 靠 NSObject 的分类方法实现的线程间通讯,GCD 靠 block。