全称是Grand Central Dispatch,🐮🍺的中枢调度器,纯C语言,提供非常多强大的函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- (void)viewDidLoad {
[super viewDidLoad];
[self gcdDemo1];
}

// 同步执行方法,这里不执行完就不会执行下一个任务
- (void)gcdDemo1 {
// 创建队列
dispatch_queue_t q = dispatch_get_global_queue(0, 0);

// 定义任务 block
void(^task)() = ^{
NSLog(@"%@", [NSThread currentThread]);
};
// 添加任务到队列并执行
dispatch_sync(q, task);
}

也可以直接写成

1
2
3
dispatch_sync(q, ^{
NSLog(@"biu");
});

异步执行,不同等待,执行下一个任务具备开启线程的能力,异步通常是多线程的代名词

1
2
3
4
5
6
7
- (void)gcdDemo2 {
dispatch_queue_t q = dispatch_get_global_queue(0, 0);
void(^task)() = ^{
NSLog(@"%@", [NSThread currentThread]);
};
dispatch_async(q, task);
}
1
2
3
4
5
6
7
8
9
- (void)gcdDemo3 {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"%@", [NSThread currentThread]);
// 更新UI
dispatch_async(dispatch_get_main_queue(0, 0), ^{
NSLog(@"更新UI%@", [NSThread currentThread]);
});
});
}

串行并行、同步异步

创建串行队列

1
2
3
dispatch_queue_t q = dispatch_queue_create("name", DISPATCH_QUEUE_SERIAL);
// 因为 DISPATCH_QUEUE_SERIAL == NULL 所以可以直接设为NULL
dispatch_queue_t q = dispatch_queue_create("name", NULL);

创建并发队列

1
dispatch_queue_t q = dispatch_queue_create("name", DISPATCH_QUEUE_CONCURRENT);

同步任务一旦开始执行,即使后面是异步任务,也不会执行异步任务,而是等同步任务执行完后再执行

异步任务中的同步任务,会在当前异步的线程中队列执行,而异步任务则还是会再开线程或被分配到闲置线程

1
2
3
4
5
6
7
8
9
10
11
12
13
- (void)gcdDemo4 {
dispatch_queue_t q = dispatch_queue_create("name", DISPATCH_QUEUE_CONCURRENT);
void (^task)() = ^{
// 假设这段代码输出 3 线程
NSLog(@"%@", [NSThread currentThread]);
// 那么下面同步任务中会等待 3 线程执行完后,再执行这个任务中的代码,也会输出 3 线程
dispatch_sync(q, ^{
NSLog(@"%@", [NSThread currentThread]);
});
};
// 把task添加到q队列
dispatch_async(q, task);
}

全局队列

本质上是并发队列,会开启线程,不会顺序执行。与并发队列不同的是有固定队列名,MRC下并发队列需要手动释放内存,全局队列不需要。但现在因为是ARC自动管理内存,所以都不需要手动释放内存。

1
dispaych_queue_t g = dispatch_get_global_queue(0, 0);
  • 参数 1

涉及到系统适配

1
2
3
4
5
6
7
8
9
10
11
12
13
// iOS 8 服务质量
QOS_CLASS_USER_INTERACTIVE // 用户交互(希望线程快速被执行,不要用耗时操作)
QOS_CLASS_USER_INITIATED // 用户需要(不要用耗时操作)
QOS_CLASS_DEFAULT // 默认的(给系统重置队列)
QOS_CLASS_UTILITY // 实用工具(做耗时操作)
QOS_CLASS_BACKGROUND // 后台执行
QOS_CLASS_UNSPECIFIED // 没有指定优先级

// iOS 7 调度的优先级
DISPATCH_QUEUE_PRIORITY_HIGH // 高优先级
DISPATCH_QUEUE_PRIORITY_DEFAULT // 默认优先级
DISPATCH_QUEUE_PRIORITY_LOW // 低优先级
DISPATCH_QUEUE_PRIORITY_BACKGROUND // 后台优先级
  • 参数 2

为未来使用的一个保留,现在始终是 0

GCD延迟执行

异步任务,经过一定的时间后,使用指定线程,执行代码块的任务

1
2
3
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"%@", [NSThread currentThread]);
});
  • 参数 1

等待时间,DISPATCH_TIME_NOW开始,等待 1.0 秒(后面参数是毫秒)

1
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC));
  • 参数 2

指定线程

  • 参数 3

代码块

执行一次

不仅能保证只执行一次,而且是线程安全

1
2
3
4
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"%@", [NSThread currentThread]);
});

调度组

组队列可以把多个队列放进组,可以做到等待所有组内队列执行完毕后再执行一些动作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 队列
dispatch_queue_t q = dispatch_get_global_queue(0, 0);
// 调度组
dispatch_group_t g = dispatch_group_create();
// 添加任务
dispatch_group_async(g, q, ^{
NSLog(@"任务一完成");
});
dispatch_group_async(g, q, ^{
NSLog(@"任务二完成");
});
dispatch_group_async(g, q, ^{
NSLog(@"任务三完成");
});
// 所有任务完成后执行的动作 传入 组、使用的线程、代码块
dispatch_group_notify(g, dispatch_get_main_queue(), ^{
NSLog(@"所有任务执行完毕");
});