再谈 GCD

来源:互联网 发布:无线端来源我的淘宝 编辑:程序博客网 时间:2024/06/06 16:44

之前针对项目简要写过一篇关于 GCD 的文章,但比较偏向应用,有些概念没有细致入微地去解释,而这些概念组合在一起十分头疼,今天就来梳理梳理,理论加实践。

GCD 中涉及到两个十分重要的概念, 就是任务和队列。

任务(Task): 你需要执行的操作,说白了就是一段代码,在GCD中,任务就是一个block;
队列(Queue): 存放任务的容器,实际上就是数组的概念,通常我们把要执行的任务放到队列中管理。

GCD 中两个重要的函数, 一个同步执行, 一个异步执行

dispatch_async(dispatch_queue_t  _Nonnull queue, ^(void)block)dispatch_sync(dispatch_queue_t  _Nonnull queue, ^(void)block)

这个函数中需要填入两个参数,一个是队列,一个是任务, 任务就是封装在 block 代码块中的. 所以, 我们在使用以上两个函数时, 只需要创建队列, 以及把自己需要执行的代码封装在 block 中就可以了。

同步与异步,串行与并发概念解读

  1. 同步和异步代表会不会开辟新的线程,串行和并发代表任务执行的方式;
  2. 同步执行没有开启新线程的能力, 所有的任务都只能在当前线程执行;
  3. 异步执行有开启新线程的能力, 但是, 有开启新线程的能力, 也不一定会利用这种能力, 也就是说, 异步执行是否开启新线程, 需要具体问题具体分析;
  4. 并发队列中的任务会放到不同的线程中去执行,串行队列中的任务只会放到同一线程中去执行;

同步执行,异步执行,并发队列,串行队列的互相组合

  1. 同步串行和同步并发,任务执行的方式是一样的。没有区别,因为没有开辟新的线程,所有的任务都是在一条线程里面执行;
  2. 异步串行和异步并发,任务执行的方式是有区别的,异步串行会开辟一条新的线程,队列中所有任务按照添加的顺序一个一个执行,异步并发会开辟多条线程,至于具体开辟多少条线程,是由系统决定的,但是所有的任务好像就是同时执行的一样。

开辟队列的方法:

dispatch_queue_t myQueue = dispatch_queue_create("MyQueue", NULL);/*    参数1:标签,用于区分队列    参数2:队列的类型,表示这个队列是串行队列还是并发队列NUll表示串行队列,DISPATCH_QUEUE_CONCURRENT表示并发队列*/

主队列与全局队列

主队列:专门负责调度主线程度的任务,没有办法开辟新的线程。所以,在主队列下的任务不管是异步任务还是同步任务都不会开辟线程,任务只会在主线程顺序执行。

主队列异步任务:现将任务放在主队列中,但是不是马上执行,等到主队列中的其它所有除我们使用代码添加到主队列的任务的任务都执行完毕之后才会执行我们使用代码添加的任务。

主队列同步任务:容易阻塞主线程,所以不要这样写。原因:我们自己代码任务需要马上执行,但是主线程正在执行代码任务的方法体,因此代码任务就必须等待,而主线程又在等待代码任务的完成好去完成下面的任务,因此就形成了相互等待。整个主线程就被阻塞了。代码示例如下:
这里写图片描述

全局队列:本质是一个并发队列,由系统提供,方便编程,可以不用创建就直接使用。

获取全局队列的方法:dispatch_get_global_queue(long indentifier.unsigned long flags)
/* 参数说明:
参数1:代表该任务的优先级,默认写0就行,不要使用系统提供的枚举类型,因为ios7和ios8的枚举数值不一样,使用数字可以通用;

参数2:苹果保留关键字,一般也写0
*/

全局队列和并发队列的区别

1,全局队列没有名字,但是并发队列有名字。有名字可以便于查看系统日志;
2,全局队列是所有应用程序共享的;
3,在mrc的时候,全局队列不用手动释放,但是并发队列需要。

最后,用一个图表简要概括一下:

这里写图片描述

尊重原创,图表来源:http://www.jianshu.com/p/0aeb2848780d