这是我参与「第四届青训营 」笔记创作活动的的第9天
Objective-C 多线程编程与 GCD(下)| 青训营笔记
GCD基本概念
线程的抽象:任务&队列
- 任务:代码在不同线程中调度的最小单元,本质是通过block保存的一段代码
- 队列:按照先进先出顺序执行的任务列表,每个队列对应至少一个线程(串行线程对应一个,并行线程对应多个)
串行队列 & 并行队列
- 串行队列:同一时刻只对应一个线程,队列中的任务按先进先出顺序,由该线程按顺序执行
- 主队列(执行在主线程):
dispatch_queue_t mainQueue = dispatch_get_main _queue(); - 并行队列:同一时刻可以对应多个线程,队列中的任务按先进先出顺序。
- 4个全局队列(每个队列对应至少一个线程,并且线程具有不同优先级),优先级由高到低,一般使用,DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_queue_t queue0 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0); dispatch_queue_t queuel = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_queue_t queue2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0); dispatch_queue_t queue3 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0); - 自行创建队列
// @param label 队列的名称,用于调试或日志 // @param attr 队列的类型,串行 DISPATCH_QUEUE_SERIAL / 并行 DISPATCH_ QUEUE_CONCURRENT // @return 创建的串行/并行队列 // 串行队列 dispatch_queue_t queue0 = dispatch_queue_create("com.yangyixuan.mySerialQueue", DISPATCH_QUEUE_SERIAL) ; // 并行队列 dispatch_queue_t queuel = dispatch_queue_create("com.yangyixuan.myConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);
添加同步任务 & 添加异步任务
- 添加同步任务:
- 不可以开启新线程,队列将该任务分配到当前线程中执行(当前线程对应指定队列)
- 当前线程执行该语句后,当前队列阻塞,等待任务执行完毕后再继续执行(相当于当前线程插入了一个任务,需要马上执行)
//添加同步任务 void dispatch_sync(dispatch_ queue_t queue, dispatch_block_t block); - 添加异步任务
- 可以开启新线程,队列将该任务分配到新的线程中执行
- 当前线程执行该语句后,当前队列不会阻塞,直接继续执行
//添加异步任务 void dispatch_async(dispatch_queue_t queue, dispatch_block_t block); - 添加同步/异步任务 到 串行/并行队列
| 到并行队列 | 到串行队列 | |
|---|---|---|
| 添加同步任务 | 当前任务阻塞 并行队列中任务在当前线程依次执行 没有意义基本不用 | 当前任务阻塞 串行队列中任务在当前线程依次执行 |
| 添加异步任务 | 当前任务不阻塞 并行队列中任务在新线程同时执行 最常用 | 当前任务不阻塞 串行队列中任务在新线程依次执行 |
注意:在一个串行队列的任务中,添加同步任务到该串行队列,会导致死锁。
GCD API实战
延时执行任务:dispatch_after
// 指定时间之后将任务追加到指定的队列
// @param when 追加任务的时间
// @param queue 任务追加到的队列
// @param block 任务
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC);
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_after(time, mainQueue, ^{ NSLog(@"等待大约(最少)3秒");});
任务分组:dispatch_group
// 创建 dispatch group
dispatch_group_t group = dispatch_group_create();
// 添加任务到 group
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_async(group, queue, block0);
dispatch_group_async(group, queue, blockl);
dispatch_group_async(group, queue, block2);
// group 中所有任务执行完成之后才在主线程执行操作
dispatch_queue_t mainQueue = dispatch_get_main_queue();
// 一组任务全部完成时通知:dispatch_group_notify
//dispatch_group_notify(group, mainQueue, ^{ NSLog(@"全部完成");});
// 设置等待时间上限,全部完成或超时时返回
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC _PER_SEC);
long result = dispatch_group _wait(group, time);
if (result == 0) {
//group 中的所有任务已经执行结束
} else {
//group 中还有任务末执行完
}
多次派发指定任务到队列:dispatch_apply
// 按照指定的次数将指定的任务追加到派发队列,并等待队列中全部任务执行结束
// @param iterations
// 追加任务的次数
// @param queue
// 任务追加到的队列
// @param block
// 任务,入参为追加的序号
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(10, queue, ^(size_t iteration)^{NSLog(@"%@", @(iteration));});
注意:dispatch_apply会等待队列中的任务执行结束,为避免死锁,应将其作为异步任务加入队列。