博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS--GCD的API的理解与使用
阅读量:6243 次
发布时间:2019-06-22

本文共 6597 字,大约阅读时间需要 21 分钟。

什么是GCD?

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

Dispatch Queue

含义是,执行处理的等待队列。 在执行处理时有两种Dispatch Queue

Serial Dispatch Queue          //  等待现在执行中处理结束Concurrent Dispatch Queue      //  不等待现在执行中处理结束复制代码

举例对比:

dispatch_async(queue, blk1);dispatch_async(queue, blk2);dispatch_async(queue, blk3);dispatch_async(queue, blk4);dispatch_async(queue, blk5);dispatch_async(queue, blk6);dispatch_async(queue, blk7);复制代码

当queue为Serial Dispatch Queue 时,因为需要等待现在执行中的处理结果,所以程序会相继执行1234567。 当queue为Concurrent Dispatch Queue时,因为不需要等待现在执行中的处理结果,所以先执行1,无论1有没有执行完都会执行2,以此类推,顺序是会改变的。此中执行方法开启的线程数量取决于当前系统的状态。

dispatch_queue_create

通过GCD的API生成Dispatch Queue。

dispatch_queue_t queue=dispatch_queue_create("com.like.same", NULL);复制代码

第一个参数指定Serial Dispatch Queue的名称,该名称会出现在应用程序崩溃时所生成的CrashLog中。可以但是不推荐为NULL。 第二个参数指定为NULL。 dispatch_queue_create函数可生成人一多个Dispatch Queue。虽然在一个Serial Dispatch Queue中同时只能执行一个追加处理,但是如果将处理分别追加到四个Serial Dispatch Queue中,各个Serial Dispatch Queue执行一个,即为同时执行四个处理。 通过dispatch_queue_creat函数生成的Dispatch Queue在使用结束后通过dispatch release函数释放。

dispatch_release(queue);复制代码
多个线程更新相同资源导致数据竞争时使用Serial Dispatch Queue。

Main Dispatch Queue/Global Dispatch Queue

获取系统标准提供的Dispatch Queue。

//   Main Dispatch Queue的获取方法    dispatch_queue_t mainQueue = dispatch_get_main_queue();        //  Global Dispatch Queue高优先级获取方法    dispatch_queue_t highQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);        //   Global Dispatch Queue默认优先级获取方法    dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);        //   Global Dispatch Queue低优先级获取方法    dispatch_queue_t lowQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);        //   Global Dispatch Queue后台优先级的获取方法    dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);复制代码

dispatch_set_target_queue

变更生成的Dispatch Queue的执行优先级要使用dispatch_set_target_queue函数。 eg:

dispatch_queue_t myQueue = dispatch_queue_create("com.like.same", NULL);        dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);        dispatch_set_target_queue(myQueue, backgroundQueue);复制代码

在必须将不可并行执行的处理追加到多个Serial Dispatch Queue中时,如果使用dispatch_set_target_queue 函数将目标指定为某一个Serial Dispatch Queue,即可防止处理并行执行。

dispatch_after

指定时间后执行处理的情况,可使用dispatch_after函数来实现。 eg:

dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3ull * NSEC_PER_SEC);        dispatch_after(time, dispatch_get_main_queue(), ^{                NSLog(@"666");            });复制代码

第一个参数时指定时间用的dispatch_time_t类型的的值。 第二个参数是指定要追加处理的Dispatch Queue。 dispatch_time函数能够获取从第一个参数dispatch_time_t类型值中指定的时间开始,到第二个参数指定的单位时间后的时间。上面的代码中第一个参数代表现在。 dispatch_time函数通常用于计算相对时间,而dispatch_walltime函数用语计算绝对时间。 eg:

dispatch_time_t getDispatchTimeByDate(NSDate * date){    NSTimeInterval interval;    double second, subsecond;    struct timespec time;    dispatch_time_t milestone;        interval = [date timeIntervalSince1970];    subsecond = modf(interval, &second);    time.tv_sec = second;    time.tv_nsec = subsecond * NSEC_PER_SEC;    milestone = dispatch_time(&time, 0);        return milestone;}复制代码

Dispatch Group

再追加到Dispatch Queue中的多个处理全部请求结束后想要执行结果处理,这种情况下使用Dispatch Group。 eg:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);    dispatch_group_t group = dispatch_group_create();        dispatch_group_async(group, queue, ^{        NSLog(@"blk0");    });    dispatch_group_async(group, queue, ^{        NSLog(@"blk1");    });    dispatch_group_async(group, queue, ^{        NSLog(@"blk2");    });        dispatch_group_notify(group, queue, ^{        NSLog(@"done");    });复制代码

打印结果为:

blk1blk0blk2done复制代码

由于多个线程并行执行,所以执行的顺序会发生改变,但是done一定是在最后输出。

另外,在Dispatch Group中也可以使用dispatch_group_wait函数仅等待全部处理执行结束。

dispatch_group_wait(group, DISPATCH_TIME_FOREVER);复制代码

第二个参数为等待的时间这里使用的是永久,也就是当处理未结束,程序将一直等待下去,中途不能取消。 如果dispatch_group_wait函数的返回值不为0,就意味着虽然经过了指定的时间,但属于Dispatch Group的某一个处理还在执行中,如果返回0,那么全部处理执行结束。 一旦调用dispatch_group_wait函数,该函数处于调用的状态而不反回。

dispatch_barrier_async

dispatch_barrier_async函数会等待追加到Concurrent Dispatch Queue上的并行执行的处理全部结束之后,再将指定的处理追加到该Concurrent Dispatch Queue中。然后由dispatch_barrier_async函数处理完毕之后,Concurrent Dispatch Queue再回复为一般动作(继续并行执行)。 eg:

dispatch_async(queue, blk0);    dispatch_async(queue, blk1);    dispatch_async(queue, blk2);    dispatch_barrier_async(queue, blk);    dispatch_async(queue, blk3);    dispatch_async(queue, blk4);    dispatch_async(queue, blk5);复制代码

执行结果恒为012在前,blk在中,345在后。

使用Concurrent Dispatch Queue和dispatch_barrier_async函数可实现高效率的数据库访问和文件访问。

图例:

dispatch_sync

dispatch_async中的“async”意味着非同步,就是将指定的Block非同步的追加到指定Dispatch Queue中,dispatch_async函数不做任何等待。 “sync”则意味着同步,就是将指定的Block非同步的追加到指定Dispatch Queue中,在追加的block结束前,dispatch_sync函数会一直等待。 eg:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);        dispatch_sync(queue, ^{        NSLog(@"上面处理已经结束");    });复制代码

一旦调用dispatch_sync函数,那么指定的处理执行结束之前,该函数不会返回。可以说是简易版的dispatch_group_wait。 dispatch_barrier_async函数的作用是在等待追加的处理全部结束之后,再追加处理到Dispatch Queue中,此外,它还与dispatch_sync函数相同,会等待追加处理的执行结果。 但是频繁使用dispatch_sync容易造成死锁。 eg:

//  造成死锁    dispatch_queue_t queue = dispatch_get_main_queue();    dispatch_sync(queue, ^{        NSLog(@"????");    });        //   同样造成死锁    dispatch_queue_t queue = dispatch_get_main_queue();    dispatch_async(queue, ^{        dispatch_sync(queue, ^{            NSLog(@"???");        });    });复制代码

dispatch_once

dispatch_once函数是保证在应用程序执行中只执行一次指定处理的API。 单例模式:

static Singleton* _instance = nil;+(instancetype) shareInstance{    static dispatch_once_t onceToken ;    dispatch_once(&onceToken, ^{    _instance = [[super allocWithZone:NULL] init] ;}) ;return _instance ;}+(id) allocWithZone:(struct _NSZone *)zone{    return [Singleton shareInstance] ;}-(id) copyWithZone:(struct _NSZone *)zone{    return [Singleton shareInstance] ;}复制代码

dispatch_apply

该函数是dispatch_sync函数和Dispatch Group的关联API。按照指定的次数将指定的Block追加到指定的Dispatch Queue中,并等待全部处理执行结束。 eg:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);        dispatch_apply(10, queue, ^(size_t index) {        NSLog(@"%zu",index);    });复制代码

由于此函数与dispatch_sync函数一样会等待处理执行结束,所以最好在dispatch_async函数中非同步的执行dispatch_apply函数。

dispatch_suspend/dispatch_resume

dispatch_suspend函数挂起指定的Dispatch Queue。

dispatch_suspend(queue);复制代码

dispatch_resume函数恢复指定的dispatch Queue。

dispatch_resume(queue);复制代码

这两个函数对已经执行的处理没有影响。挂起后,追加到Dispatch Queue中但尚未执行的处理在此之后停止执行。而恢复能使这些处理能够继续执行。

Dispatch Semaphore

待续。。。。

转载地址:http://bvpia.baihongyu.com/

你可能感兴趣的文章
通过DAC来连接SQL Server
查看>>
Oracle11G 卸载步骤
查看>>
Mars说光场(3)— 光场采集
查看>>
kettle与各数据库建立链接的链接字符串
查看>>
Android--调用系统照相机拍照与摄像
查看>>
【OpenCV学习】利用HandVu进行手部动作识别分析
查看>>
Ubuntu下安装配置JDK1.7
查看>>
AngularJS快速入门指南15:API
查看>>
安装惠普M1136打印机一直处于“新设备已连接”状态怎么办?
查看>>
android88 录音机
查看>>
美国诚实签经验(最全集合)
查看>>
HttpContext.Current:异步模式下的疑似陷阱之源
查看>>
《Java与模式》- 创建型模式
查看>>
[Android]使用Kotlin开发Android(二)
查看>>
php将对象数组转成普通数组
查看>>
org.gradle.process.internal.ExecException: Process 'command 'C:\Program Files (x86)\Java\jdk1.7.0_7
查看>>
Python 中的 if __name__ == '__main__' 该如何理解(1)
查看>>
Qt之对话框设计——利用QPalette改变控件颜色
查看>>
#lspci | grep Eth
查看>>
Linux下svn常用指令【转】
查看>>