什么是GCD?
Grand Central Dispatch或者GCD,是一套底层API,提供了一种新的方法来进行并发程序编写。使用GCD来提升程序性能以及发挥多核系统优势.
GCD的工作原理:
让程序平行的特定任务,根据可用的处理资源,安排他们在任何可用的处理器核心上执行任务.
GCD提供了很多超越传统多线程编程的优势.
-
简单易用,居于block的血统,导致它能极为简单的在不同代码作用域之间传递上下文,
-
效率,它在很多地方比之专门创建消耗资源的线程更实用且快速,
-
性能,GCD自动根据系统负载来增减线程数量.这就减少了上下文切换以及增加了计算效率.
GCD中有三种队列类型:
- The main queue: 与主线程功能相同。实际上,提交至main queue的任务会在主线程中执行。main queue可以调用dispatch_get_main_queue()来获得。因为main queue是与主线程相关的,所以这是一个串行队列。
- Global queues: 全局队列是并发队列,并由整个进程共享。进程中存在三个全局队列:高、中(默认)、低三个优先级队列。可以调用dispatch_get_global_queue函数传入优先级来访问队列。
- 用户队列: 用户队列 (GCD并不这样称呼这种队列, 但是没有一个特定的名字来形容这种队列,所以我们称其为用户队列) 是用函数 dispatch_queue_create 创建的队列.
有4个术语比较容易混淆:同步、异步、并发、串行
同步和异步决定了要不要开启新的线程
-
同步: 在当前线程中执行任务,不具备开启新线程的能力
-
异步: 在新的线程中执行任务,具备开启新线程的能力
并发和串行决定了任务的执行方式
-
并发: 多个任务并发(同时)执行
-
串行: 一个任务执行完毕后,再执行下一个任务
尽管GCD是纯c语言的,但它被组建成面向对象的风格。GCD对象被称为dispatch object。Dispatch object像Cocoa对象一样是引用计数的。
dispatch_resume() 继续执行线程
dispatch_suspend() 挂起线程 中断线程
dispatch_sync() 同步添加操作。他是等待添加进队列里面的操作完成之后再继续执行。
dispatch_async () 异步添加进任务队列,它不会做任何等待
dispatch_get_main_queue() 主队列是GCD自带的一种特殊的串行队列,放在主队列中的任务,都会放到主线程中执行
dispatch_queue_create() 创建一个队列
第一个参数是一个标签,这纯是为了debug。Apple建议我们使用倒置域名来命名队列,比如“com.dreamingwish.subsystem.task”。这些名字会在崩溃日志中被显示出来,也可以被调试器调用这在调试中会很有用,所有尽量不要重名了。
第二个参数 设置你的队列是否串行或并行.一般我是设置NULL,它是串行
DISPATCH_QUEUE_SERIAL | DISPATCH_QUEUE_CONCURREN
dispatch_get_global_queue() 全局并发队列,并由整个进程共享, 可设定优先级来选择高、中、低, 后台优先级队列。说明:全局并发队列的优先级
#define DISPATCH_QUEUE_PRIORITY_HIGH 2 // 高
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 // 默认(中)
#define DISPATCH_QUEUE_PRIORITY_LOW (-2) // 低
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 后台
dispatch_group_create()创建一个调度任务组 它可以将对象关联
dispatch_group_async(dispatch_group_t group, dispatch_queue_t queue, dispatch_block_t block);
group 提交到的任务组,这个任务组的对象会一直持续到任务组执行完毕
queue 提交到的队列,任务组里不同任务的队列可以不同
block 提交的任务
func dispatchgroup_notify( group: dispatchgroup_t!, queue: dispatch_queue_t!,_block: dispatch_block_t!)
group监听的任务组
queue 执行完毕的这个闭包所在的队列
block执行完毕所响应的任务
dispatch_group_wait 设置等待时间,在等待时间结束后,如果还没有执行完任务组,则返回。返回0代表执行成功,非0则执行失败
dispatchgroup_enter/dispatch_group_leavefunc dispatch_group_enter( group: dispatchgroup_t!)func dispatch_group_leave( group: dispatch_group_t!)
这两个方法显示的讲任务组中的任务未执行完毕的任务数目加减1,这种方式用在不使用dispatch_group_async来提交任务
注意:这两个函数要配合使用,有enter要有leave,这样才能保证功能完整实现。也可以用这对函数来让一个闭包关联多个Groupdispatch_group_notify 用来监听任务组事件的执行完毕
void dispatch_apply(size_t iterations, dispatch_queue_t queue,void (^block)(size_t)) 这个函数调用单一block多次,并平行运算,然后等待所有运算结束,作用是把指定次数指定的block添加到queue中
第一个参数是迭代次数
第二个是所在的队列
第三个是当前索引
看完上面的介绍,下面来简单的使用GCD吧.
一个在异步执行的串行队列,如若想并发执行将DISPATCH_QUEUE_SERIAL换成DISPATCH_QUEUE_CONCURRENT即可.
串行队列只会创建一条异步线程,并发队列将会创建多个线程
array = @[@"guo",@"bin",@"ai",@"chun",@"yan"];
dispatch_queue_t serialQueue = dispatch_queue_create("BIn.text", DISPATCH_QUEUE_SERIAL);
for (id obj in array) {
dispatch_async(serialQueue, ^{
for (int i = 1; i <= 100; i++) {
NSLog(@"%@ = %d",obj,i);
}