2️⃣GCD API讲解<一>

来源:互联网 发布:网络防诈骗方法 编辑:程序博客网 时间:2024/06/05 16:49

我们回顾一下上一节讲的苹果官方给出的GCD的说明:
开发者要做的只是定义想执行的任务并追加到适当的Dispatch Queue中
源代码表示就是

dispatch_async(queue,^{    /**    * 想执行的任务    */});

该源代码使用block语法定义想要执行的任务,通过dispatch_async函数追加赋值在变量queue的Dispatch Queue中,这样就可以执行block在另外一个线程中执行.
Dispatch Queue 如其名称所示,是执行处理的等待队列.应用编程人员通过dispatch_async函数等API,在block语法中记述想执行的处理并追加到Dispatch Queue中.Dispatch Queue按照追加的顺序执行(先进先出 FIFO First-In-First-Out)处理.
另外在执行处理时存在两种Dispatch Queue,一种是等待现在执行中处理的Serial Dispatch Queue(串行队列),另一种是不等待现在执行中处理的Concurrent Dispatch Queue(并行队列).
这两种队列的区别在于一个等待现在执行中处理,一个不等待现在执行中处理.
准备以下源码:在dispatch_async追加多个处理.

//这是Serial Dispatch Queue(串行队列) dispatch_queue_t queue = dispatch_queue_create("com.gcd.queue", NULL);    for (int i = 0; i<10; i++) {        dispatch_async(queue, ^{            NSLog(@"%d",i);        });    }    log信息为: 0 1 2 3 4 5 6 7 8当queue为Concurrent Dispatch Queue (并行队列)dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);    for (int i = 0; i<10; i++) {        dispatch_async(queue, ^{            NSLog(@"%d",i);        });    } log信息为: 2 0 3 4 5 6 1 8 9 7

这就说明了:
当变量queue为Serial Dispatch Queue时,因为要等待现在处理中的处理结束,所以是按照顺序执行的.同时执行的处理数只能有1个,
当变量queue为Concurrent Dispatch Queue时,因为不用等待现在执行中的处理,所以首先执行的是i=0时的操作,不管这个block有没有执行完,都开始执行后面的block,可以并行执行多个处理.但执行的数量取决于当前系统的状态,即iOS和OS X基于Dispatch Queue中的处理数、CPU核数以及CPU负荷等当前系统的状态来决定Concurrent Dispatch Queue 中并行执行的数量.所谓”并行执行”,就是使用多个线程同时执行多个处理.
如图
这里写图片描述

iOS和OSX的核心—-XNU内核决定应当使用的线程数,并只生成所需的线程执行处理.当处理结束,应当执行的处理数减少时,XNU内核会结束不再需要的线程.XNU内核仅使用Concurrent Dispatch Queue便可完美的管理并执行多个处理的线程.
如何得到Serial Dispatch Queue 和 Concurrent Dispatch Queue 呢
(一) dispatch_queue_create
第一种是通过GCD的API生成Dispatch Queue
通过dispatch_queue_create可生成Dispatch Queue
Serial Dispatch Queue

dispatch_queue_t queue = dispatch_queue_create("com.gcd.queue", NULL);

在说明dispatch_queue_create之前,先说一下Serial Dispatch Queue 生成个数的注意事项.
Concurrent Dispatch Queue 并行执行多个追加处理,而Serial Dispatch Queue只能执行1个追加处理.虽然这两种受到系统资源的限制,但用dispatch_queue_create函数可生成任意多个Dispatch Queue
当生成多个Serial Dispatch Queue时,多个Serial将并行执行.虽然一个Serial Dispatch Queue中同时只能执行一个处理,单如果追加到4个Serial Dispatch Queue中,各个Serial Dispatch Queue执行1个,即为同时执行4个处理.

这里写图片描述

一旦生成Serial Dispatch Queue并追加处理,系统会对一个Serial Dispatch Queue就只生成一条线程,如果生成2000个Serial Dispatch Queue,那么久生成2000个线程.像之前的多线程编程问题一样,如果使用过多的线程,就会消耗大量的内存,引起大量的上下文切换,大幅度降低系统的响应性能.

只在为了避免多线程编程问题之一——多个线程更新相同资源导致数据竞争时使用Serial Dispatch Queue.
这里写图片描述
但是Serial Dispatch Queue的等成个数应当仅限所必需的数量,例如一个数据库表更新生成1个Serial Dispatch Queue即可,更新一个文件或者一个文件快生成1个Serial Dispatch Queue,虽然Serial Dispatch Queue比Concurrent Dispatch Queue可以生成更多的线程,但是不能激动之下生成大量的Serial Dispatch Queue.
当想并行执行不发生数据竞争的问题处理时,使用Concurrent Dispatch Queue.对于Concurrent Dispatch Queue来说,不管生成多少,由于XNU内核只使用有效管理的线程,因此不会发生Serial Dispatch Queue 的问题.
这个问题说明之后,继续来讲dispatch_queue_create这个函数.

//回顾一下Serial Dispatch Queue生成代码dispatch_queue_t queue = dispatch_queue_create("com.gcd.queue", NULL);

第一个参数指定Serial Dispatch Queue的名称.像此源代码一样,Dispatch Queue的名称推荐使用应用程序的ID这种逆序全程域名(FQDN fully qualified domain name).改名称在Xcode和Instruments的调试器中作为Dispatch Queue名称表示.另外,该名称也出现在应用程序崩溃时所产生的CrashLog中.我们命名时应遵循这样的原则:对于我们编程人员来说简单易懂.如果嫌命名麻烦也可以设为NULL,但是后期调试你会后悔的.
第二个参数指定生成队列的类型
生成Serial Dispatch Queue时指定为NULL就可以
生成Concurrent Dispatch Queue指定为DISPATCH_QUEUE_CONCURRENT

dispatch_queue_t queue = dispatch_queue_create("com,gcd.queue", DISPATCH_QUEUE_CONCURRENT);

dispatch_queue_create返回值为表示Dispatch Queue的”dispatch_queue_t”类型.在之前源代码表示中queue均为此类型.

dispatch_queue_t queue = dispatch_queue_create("com,gcd.queue", DISPATCH_QUEUE_CONCURRENT);    dispatch_async(queue, ^{        NSLog(@"block on queue");    });

该源码在Concurrent Dispatch Queue中执行指定的block.
遗憾的是在ios6.0之前尽管ARC这一通过编译自动管理内存的优秀技术,但是生成的Dispatch Queue必须由程序员释放.这是因为Dispatch Queue并没有像Block那样具有作为Object-C对象处理的技术.
通过dispatch_queue_create创建的线程需要通过dispatch_release函数释放.ios6.0之后就不需要了.

0 0
原创粉丝点击