iOS-多线程:GCD
一、概述
多核并行运算,自动管理线程的声明周期,基于C语言编写
二、任务、队列
任务:
任务就是要执行的操作,要做的事情。在GCD的block中执行。执行又分为“同步执行”、“异步执行”。
同步执行(dispatch_sync):把任务添加到队列不会开启线程,任务按照顺序执行。
异步执行(dispatch_async):把任务添加到队列具备开启线程的能力,任务可以同时执行。
队列:
队列指执行任务的等待队列,采用FIFO原则。队列分为:串行队列、并行队列。
串行队列:每次执行一个任务,按照顺序一个一个的执行。默认为主队列。
并行队列:可以一次执行多个任务(可以开启多个线程,同时执行任务)。并发队列只有在异步执行的情况下才会开启多线程。默认为全局并发队列。
三、GCD的使用
分为两步:
(1)创建队列
(2)把任务添加到队列中
1.创建队列
// 串行队列的创建方法
dispatch_queue_t queue = dispatch_queue_create("队列标识", DISPATCH_QUEUE_SERIAL);
// 并发队列的创建方法
dispatch_queue_t queue = dispatch_queue_create("队列标识", DISPATCH_QUEUE_CONCURRENT);
//获得主队列
dispatch_queue_t queue = dispatch_get_main_queue();
// 全局并发队列的获取方法
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
2.创建任务
// 同步执行任务创建方法
dispatch_sync(queue, ^{
// 这里放同步执行任务代码
});
// 异步执行任务创建方法
dispatch_async(queue, ^{
// 这里放异步执行任务代码
});
四、不同的组合方式
并行队列 串行队列
同步 不开线程,串行执行 不开线程,串行执行
异步 开线程,并行执行 开 1 条线程,串行执行
五、线程间通信
线程间通信:一般都是在主线程中刷新UI操作。耗时操作(网络请求,数据加载)放在子线程中进行,当耗时操作完成,回到主线程刷新UI。
dispatch_async(queue, ^{
// 异步追加任务
// 回到主线程
dispatch_async(mainQueue, ^{
// 追加在主线程中执行的任务
});
});
六、其他方法
1.栅栏函数:dispatch_barrier_async
异步执行的两个任务,第一个任务执行完毕之后执行栅栏方法然后进行第二个任务执行。
dispatch_async(queue, ^{
// 追加任务 1
});
dispatch_async(queue, ^{
// 追加任务 2
});
dispatch_barrier_async(queue, ^{
// 追加任务 barrier
});
dispatch_async(queue, ^{
// 追加任务 3
});
2.延迟方法:dispatch_after
//延迟3秒后,执行操作
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 2.0 秒后异步追加任务代码到主队列,并开始执行
});
3.只执行一次:dispatch_once
整个程序运行过程中只执行一次的代码时,使用 dispatch_once 方法(多用于单例)
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 只执行 1 次的代码
});
4.迭代:dispatch_apply
指定的次数将指定的任务追加到指定的队列中,并等待全部队列执行结束
dispatch_apply(次数, 队列, ^(size_t index) {
});
5.队列组:dispatch_group
异步执行多个耗时任务,等任务全部执行完毕再回到主线程。
调用队列组的 dispatch_group_notify 回到指定线程执行任务
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 追加任务 1
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 追加任务 2
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 任务 1、任务 2 都执行完毕后,回到主线程执行下边任务
});