一.什么是GCD
- 全称是Grand Central Dispatch,可译为“牛逼的中枢调度器”
纯C语言,提供了非常多强大的函数 - GCD的优势
GCD是苹果公司为多核的并行运算提出的解决方案
GCD会自动利用更多的CPU内核(比如双核、四核)
GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)
程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码
二.GCD基本知识
1. 两个核心概念
1) 队列:执行什么操作
并发队列:允许多个任务同时执行
串行队列:串行队列:只能一个接着一个的执行
2) 任务:用来存放任务
** 队列,都是用来存放任务,任务:执行什么操作
2. 同步函数和异步函数
同步:只能在当前线程中执行任务,不具备开启新线程的能力
异步:可以在新的线程中执行任务,具备开启新线程的能力
三.GCD的使用
- 定制任务 确定想做的事情
- 将任务添加到队列中
- GCD会自动将队列中的任务取出,放到对应的线程中执行
- 任务的取出遵循队列的FIFO原则:先进先出,后进后出
执行任务:
- GCD中有两个用来执行任务的常用函数
同步:只能在当前线程中执行任务,不具备开启新线程的能力
dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
异步:可以在新的线程中执行任务,具备开启新线程的能力
dispatch_async(dispatch_queue_t queue, dispatch_block_t block)
GCD中还有个用来执行任务的函数:
dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);
注意:在前面的任务执行结束后它才执行,而且它后面的任务等它执行完成之后才会执行,这个queue不能是全局的并发队列
- 并发队列:允许多个任务同时执行
1)直接create dispatch_queue_create
第一个参数:标签 队列的名称 C语言
第二个参数:队列的类型
*/
dispatch_queue_t queue = dispatch_queue_create("com.seemygo.www.download", DISPATCH_QUEUE_CONCURRENT);
2)全局并发队列
/*
第一个参数:优先级
第二个参数:留给未来使用的0
*/
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
全局并发队列的优先级
#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 // 后台
- 串行队列:只能一个接着一个的执行
1)直接create dispatch_queue_create
dispatch_queue_t queue = dispatch_queue_create("com.seemygo.www.download", DISPATCH_QUEUE_SERIAL); // 创建串行队列(队列类型传递NULL或DISPATCH_QUEUE_SERIAL)
2)主队列:
1)所有在主队列中的任务都会被放在主线程中执行
2)主队列中的任务在执行之前会先检查主线程的状态,
如果发现主线程当前正在执行任务那么会暂停队列中任务的调度***
同步:必须要得到该方法的返回值才能够继续往下执行--->如果我没有执行完毕,那么后面的将永远无法执行
异步:可以继续往下执行,等前面的任务执行完毕之后再回头执行-->我无所谓,你可以先执行后面的代码
dispatch_queue_t queue = dispatch_get_main_queue();
- 各种队列的执行效果
并发队列 | 手动创建的串行队列 | 主队列 | |
---|---|---|---|
同步(sync) | 没有开启新线程 串行执行任务 | 没有开启新线程 串行执行任务 | 没有开启新线程 串行执行任务 |
异步(async) | 有开启新线程 并发执行任务 | 有开启新线程 串行执行任务 | 没有开启新线程 串行执行任务 |
注意:使用sync函数往当前串行队列中添加任务,会卡住当前的串行队列(死锁)
总结: GCD基本使用
01 异步函数+并发队列:开启多条线程,并发执行任务
02 异步函数+串行队列:开启一条线程,串行执行任务
03 同步函数+并发队列:不开线程,串行执行任务
04 同步函数+串行队列:不开线程,串行执行任务
05 异步函数+主队列:不开线程,在主线程中串行执行任务
06 同步函数+主队列:不开线程,串行执行任务(注意死锁发生)
07 注意同步函数和异步函数在执行顺序上面的差异
补充:
使用Crearte函数创建的并发队列和全局并发队列的主要区别:
1)全局并发队列在整个应用程序中本身是默认存在的并且对应有高优先级、默认优先级、低优先级和后台优先级一共四个并发队列,我们只是选择其中的一个直接拿来用。而Create函数是实打实的从头开始去创建一个队列。
2)在iOS6.0之前,在GCD中凡是使用了带Create和retain的函数在最后都需要做一次release操作。而主队列和全局并发队列不需要我们手动release。当然了,在iOS6.0之后GCD已经被纳入到了ARC的内存管理范畴中,即便是使用retain或者create函数创建的对象也不再需要开发人员手动释放,我们像对待普通OC对象一样对待GCD就OK。
3)在使用栅栏函数的时候,苹果官方明确规定栅栏函数只有在和使用create函数自己的创建的并发队列一起使用的时候才有效(没有给出具体原因)不能使用全局并发队列
4)其它区别涉及到XNU内核的系统级线程编程,不一一列举。