GCD API函数整理

2016-05-10  本文已影响84人  凌巅

GCD API函数整理

GCD(Grand Central Dispatch)是异步执行任务的技术之一,一般将应用程序中记述的线程管理用的代码在系统级中实现。开发者只要定义想执行的任务并追加到适当的Dispatch Queue中,GCD就能生成<strong>必要的线程</strong>并计划执行任务。由于线程管理是作为系统的一部分来实现的,因此可统一管理,也可执行任务,比以前的线程更加有效率。

(一)Dispatch Queue

Dispatch Queue 如其名称所示,是执行处理的等待队列。开发人员通过dispatch_async函数等API,将要执行任务的block追加到Dispatch Queue中。Dispatch Queue按照追加顺序(先进先出 FIFO)执行处理。

Dispatch Queue的两种种类

| Dispatch Queue的种类 | 说明 |
| ---------------------- --|:----------------------------:|
| Serial Dispatch Queue | 等待现在执行中的处理结束 (串行) |
| Concurrent Dispatch Queue| 不等待现在执行中处理结束 (并行) |

Dispatch Queue的创建

dispatch_queue_create dispatch_release dispatch_retain Dispatch Queue管理API

dispatch_queue_create用法:

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

该函数的第一个参数指定Dispatch Queue的名称,推荐使用逆序全程域名,该名称在Xcode和Instrument的调试器中作为Dispatch Queue名称表示,另外改名字也出现在应用程序崩溃时所生成的CrashLog中。
第二个参数指定为Dispatch Queue的种类。NULL则生成Serial Dispatch Queue.指定为DISPATCH_QUEUE_CONCURRENT则生成Concurrent Dispatch Queue。
该函数的返回类型是dispatch_queue_t类型。
注意:生成Serial Dispatch Queue队列时,系统中的线程和队列是一一对应的,一个Serial Dispatch Queue队列生成并使用一个线程。如果生成2000个Serial Dispatch Queue队列,那么就会生成2000个线程。而对于Concurrent Dispatch Queue来说,不管生成多少,由于XNU内核只使用有效管理的线程。
</br>
dispatch_release 用法:

dispatch_release(mySerialDispacthQueue);

释放自定义创建的队列
</br>
dispatch_retain 用法:

dispatch_retain(mySerialDispacthQueue);

增加队列的引用计数

系统Queue的获取

系统会为我们提供几个Dispatch Queue,那就是Main Dispatch Queue和Global Dispatch Queue。
Main Dispatch Queue是在主线程中执行的Dispatch Queue,主线程只有一个,这个Queue也就是Serial Dispatch Queue
Global Dispatch Queue是所有应用程序都能够使用的Concurrent Dispatch Queue,一般情况下,没有必要通过dispatch_queue_create函数逐个生成Concurrent Dispatch Queue,只要获取Global Dispatch Queue即可。
此外,Global Dispatch Queue有四个执行优先级,高优先级,默认优先级,低优先级,后台优先级。在向Global Dispatch Queue追加处理时,应该选择与处理内容对应的执行优先级的Global Dispatch Queue。

dispatch_get_main_queue 获取Main Dispatch Queue API

dispatch_get_main_queue 用法:

dispatch_queue_t mainQueue = dispatch_get_main_queue();

dispatch_get_global_queue 获取Global Dispatch Queue API

Global Dispatch Queue 用法:

dispatch_queue_t globalQueue = dispatch_get_global_queue(long identifier, unsigned long flags);

函数参数介绍:第一个参数,指定获取global queue的优先级,有四个取值标示:
DISPATCH_QUEUE_PRIORITY_HIGH 最高优先级
DISPATCH_QUEUE_PRIORITY_DEFAULT 默认优先级
DISPATCH_QUEUE_PRIORITY_LOW 低优先级
DISPATCH_QUEUE_PRIORITY_BACKGROUND 后台优先级
第二个参数:保留,目前送0

Dispatch Queue执行优先级的变更

使用dispatch_queue_create创建的Dispatch Queue都使用与默认优先级Global Dispatch Queue相同执行优先级的线程。如果要变更执行优先级要使用dispatch_set_target_queue函数。

dispatch_set_target_queue 变更创建Dispatch Queue的执行优先级API

dispatch_set_target_queue 用法:

dispatch_queue_t mySerialDispacthQueue =
        dispatch_queue_create("com.example.gcd.mySerialDispacthQueue",NULL);  
dispatch_queue_t globalQueueHigh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);  
dispatch_set_target_queue(mySerialDispacthQueue,globalQueueHigh);

函数参数介绍:第一个参数,指定需要变更优先级的Dispatch Queue。
第二个参数,参考执行优先级的Dispatch,Queue,即把第一个参数代表的Queue的执行优先级设为和第二个参数代表的Queue的优先级相同

dispatch_time 获取dispatch_time_t类型的值

dispatch_time 用法:

dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW,1ull * NSEC_PER_SEC);

函数从第一个参数dispatch_time_t类型值中指定的时间开始,到第二个参数指定的毫微妙单位时间后的时间。第一个参数经常是:DISPATCH_TIME_NOW,表示现在时间。代码中表示,从现在开始1秒后的时间。这里是用NSEC_PER_SEC(秒)为单位。,如果使用NSEC_PER_MSEC则表示以毫秒为单位。
此外:还有一个函数:dispatch_walltime 用于计算绝对时间
dispatch_walltime(const struct timespec *when, int64_t delta);传入一个timespec类型的时间。

Dispatch Group组管理

当追加到Dispatch Queue中多个处理全部结束后,想执行结束处理。只使用一个Serial Dispatch Queue(串行)时,只要将想执行的处理全部追加到该Serial Dispatch Queue中,并在最后追加结束处理,即可实现。但是在使用Concurrent Dispatch Queue时或者同时使用多个Dispatch Queue时,就变的很复杂了。。
在这种情况下,就可以使用Dispatch Group.

dispatch_group_creat dispatch_group_asysnc,dispatch_group_notify,dispatch_group_wait,dispatch_release API

dispatch_group_creat 创建dispatch_group_t类型的Dispatch Group。
用法 :

dispatch_group_t group = dispatch_group_creat();

dispatch_group_asysnc 将相应Dispatch Queue和需要执行的block追加到Dispatch Group中
用法:

dispatch_group_async(group,queue,^{NSLog("blk0");});

dispatch_group_notify 监视组内的任务执行情况,当执行dispatch_group_notify追加的任务是,组内的任务都已经执行结束。
用法:

dispatch_group_notify(group,dipatch_get_main_queue(),^{NSLog(@"done");});

dispatch_group_wait 等待全部处理执行结束
用法

dispatch_group_wait(group,DISPATCH_TIME_FOREVER);

该函数的第二个参数指定为等待时间(dispatch_time_t类型),上述代码中使用DISPATCH_TIME_FOREVER,表示永久等待。只要属于Dispatch Group的处理尚未执行结束,就会一直等待,中途不能取消。
dispatch_release 释放Dispatch Group
用法:

dispatch_release(group);

dispatch_barrier_async 并发控制 API

dispatch_barrier_async 允许在一个并发队列中创建一个同步点。当在并发队列中遇到一个barrier, 他会延迟执行barrier的block,等待所有在barrier之前提交的blocks执行结束。 这时,barrier block自己开始执行。 之后添加的block继续正常的执行操作。
用法:

.
.
dispatch_async(queue,blk_for_reading);  //读操作
dispatch_barrier_async(queue,blk_for_writing); //写操作  
dispatch_async(queue,blk_for_reading); //读操作 
.
. 

dispatch_sync dispatch_async 同步 or 非同步

dispatch_sync 同步执行添加的Block 函数一直等待Block任务执行完
用法:

dispatch_sync(queue,^{NSLog(@"block!");});

dispatch_aync 非同步执行添加的Block 函数不做任何等待
用法:

dispatch_async(queue,^{NSLog(@"block!");};)

dispatch_apply 批量添加任务Block

dispatch_apply 按指定的次数将指定的Block追加到指定的Dispatch Queue中,并等待全部处理执行结束。

dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(10,queue,^(size_t index){
    NSLog("%zu",index);
    )};
    NSLog("done");

第一个参数:重复次数
第二个参数:追加对象执行的Dispatch Queue
第三个参数:追加的处理,与之前的形式不同,这个Block为带有参数的Block,这个参数为追加Block的顺序标号,区分各个Block;

dispatch_suspend / dispatch_resume 挂起和执行

dispatch_suspend 挂起指定的Dispatch Queue
用法:

dispatch_suspend(queue);  

dispatch_resume 恢复指定的Dispatch Queue
用法:

dispatch_resume(queue);

Dispatch Semaphore 持有计数的信号

dispatch_semaphore_create 生成dispatch_semaphore_t类型的计数信号

dispatch_semaphore_t semaphore = dispatch_semaphore_create(1)

创建初始值为1
dispatch_semaphore_wait 等待Dispatch Semaphore的计数值达到大于或等于1,当计数值大于等于1,或者在待机中计数值大于等于1,对该计数值做减法并返回。

dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);

第一个参数:所以等待的对象计数信号
第二个参数: 等待时间,和dispatch_group_wait类似
dispatch_semaphore_signal 将Dispatch Semaphore的计数值加1

dispatch_once

dispatch_once 保证在应用程序执行中只执行一次指定处理
用法:

static dispatch_once_t pred;
dispatch_once(&pred,^{
    //初始化代码
});

通过dispatch_once函数,即使在多线程环境中下执行,也可保证百分百安全。在生成单例时使用

上一篇下一篇

猜你喜欢

热点阅读