狮子头镇楼
《Objective-C 高级编程》学习笔记2-Blocks
1 什么是 GCD
将应用程序中记述的线程管理用的代码在系统级中实现。开发者只需要定义想要执行的任务并追加到适当的 Dispatch Queue 中,GCD就能生成必要的线程并计划执行任务。
2 GCD 的 API
dispatch_async(queue, ^{
/*
* 想执行的任务
*/
})
该源码使用 Block 语法“定义想执行的任务”,通过 dispatch_async
函数“追加”赋值在变量 queue
的“Dispatch Queue中”。
2.1、Dispatch Queue
Dispatch Queue:执行处理的等待队列。有两种:
- Serial Dispatch Queue,串行队列
- Concurrent Dispatch Queue,并行队列
2.2、dispatch_queue_create
//创建串行队列
dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("com.gcd.mySerialDispatchQueue", NULL);
dispatch_async(mySerialDispatchQueue, ^{
//在串行队列中执行Block
});
//创建并行队列
dispatch_queue_t myConcurrentDispatchQueue = dispatch_queue_create("com.gcd.myConcurrentDispatchQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(myConcurrentDispatchQueue, ^{
//在并行队列中执行Block
});
2.3、Main Dispatch Queue / Global Dispatch Queue
这是系统标准提供的 Dispatch Queue
2.3.1、Main Dispatch Queue
主线程执行的的 Dispatch Queue,因为主线程只有一个,所以它一定是串行队列
追加到 Main Dispatch Queue 的处理在主线程的 RunLoop 中执行。因此用户界面的操作等一些必须在主线程中执行的处理追加到 Main Dispatch Queue 中使用。
2.3.2、Global Dispatch Queue
是所有应用程序都能够使用的并行队列,它有四个优先级。
///主队列获取
dispatch_queue_t mdq = dispatch_get_main_queue();
//全局队列,执行优先级:高
dispatch_queue_t gdq_high = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
//全局队列,执行优先级:中
dispatch_queue_t gdq_default = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//全局队列,执行优先级:低
dispatch_queue_t gdq_low = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
//全局队列,执行优先级:后台
dispatch_queue_t gdq_background = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
2.4、dispatch_set_target_queue
dispatch_queue_create
函数生成的 Dispatch Queue
不管是 串行队列 还是 并行队列,都使用与默认优先级 Global Dispatch Queue
相同执行优先级的线程。可使用 dispatch_set_target_queue
函数变更 Dispatch Queue
的执行优先级。
2.5、dispatch_after
可使用 dispatch_after
执行指定时间后执行的处理。注意:dispatch_after
函数并不是在指定时间后执行处理,而只是在指定时间追加处理到 Dispatch Queue
。
dispatch_time_t dt = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
dispatch_after(dt, dispatch_get_main_queue(), ^{
//执行操作的block
});
2.6、Dispatch Group
在追加到 Dispatch Queue 中的多个处理全部结束后想执行结束处理的时候使用。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{ NSLog(@"blk0"); });
dispatch_group_async(group, queue, ^{ NSLog(@"blk1"); });
dispatch_group_async(group, queue, ^{ NSLog(@"blk2"); });
dispatch_group_async(group, queue, ^{ NSLog(@"blk3"); });
dispatch_group_notify(group, dispatch_get_main_queue(), ^{ NSLog(@"done"); });
2.7、dispatch_sync
- async 意味着 “非同步”,dispatch_async 函数不做任何等待。
- sync 意味着 “同步”,dispatch_sync 函数会将指定的 Block “同步” 追加到指定的 Dispatch Queue 中。在追加 Block 结束之前,dispatch_sync 函数会一直等待。
dispatch_sync 使用不当会造成一个很严重的问题:死锁。
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"同步任务在 %@ 执行", [NSThread currentThread]);
});
//1、主线程正在执行主队列的任务;
//2、一个同步任务过来了,于是,主线程立即等待;
//3、同步任务在等主线程当前任务完成,然而主线程在等待这个同步任务执行;
//4、于是就造成了相互等待的情况。
2.8、dispatch_once
dispatch_once 函数是保证在应用程序执行中只执行以此指定处理的API。如初始化单例。
+ (instancetype)share {
static id instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
3 GCD 实现
3.1、Dispatch Queue
GCD 的 Dispatch Queue 非常方便,实现 GCD 需要:
- 用于管理追加的 Block 的 C语言层实现的 FIFO 队列。
- Atomic 函数中实现的用于排他控制的轻量级信号。
- 用于管理线程的C语言层实现的一些容器。