GCD之任务分发函数进阶

在前一篇文章,我们介绍了GCD的基本使用,其中就包含分发函数这一节,详细介绍了dispatch_async和dispatch_sync两个分发函数。今天我们就来探讨一下更多的分发函数,从而体验GCD中更高级的功能。对于分发函数中_f结尾的函数,不再进行详细介绍,有_f和没有_f的分发函数,不同点就是_f是把任务封装成C函数,而不带_f是把任务封装成block。

GCD的任务分发函数除了之前介绍的两个之外,还有以下几个:dispatch_after、dispatch_apply和dispatch_once,每个函数的名称都突出了函数的功能,学习这些函数是,可以注意函数名及其功能之间的关系,以增强理解。下面我们一一的学习这几个分发函数。

1. dispatch_after,这个函数的声明是:

void dispatch_after ( dispatch_time_t when, dispatch_queue_t queue, dispatch_block_t block );

可以看出,这个函数只是比dispatch_async多了一个参数(when)。其实,这个函数的功能跟dispatch_async也很类似,此函数也是异步分发函数,调用之后会立即返回,无需等待分发的任务执行完成。但是,此函数相对于dispatch_async增加了一项功能,就是延时分发,即等待when参数给定的时间之后,在把任务分发到对应的queue中。等待时间参数(when)可以通过dispatch_time函数获取。具体使用如下:

    // 获取等待时间参数值,其中DISPATCH_TIME_NOW表示延时的开始计算时间(此处为当前时间),NSEC_PER_SEC代表延时的时间单位(此处为秒),10代表时长
    dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC));
    // 把任务封装成block,延时10秒分发到mainQueue中
    dispatch_after(when, dispatch_get_main_queue(), ^{

        // 待执行的任务代码
    });

注意:如果延时时间为0,直接使用dispatch_async会有更高的效率。

2.dispatch_apply,函数的声明如下:

void dispatch_apply ( size_t iterations, dispatch_queue_t queue, void (^block)(size_t) );

dispatch_apply就是进行循环分发,把任务循环分发指定次数到相应的队列中。此函数也是异步分发,函数会立即返回,无需等待任务执行完成。下面是dispatch_apply的应用,及与其等效的for循环实现:

    // 循环10次分发block,block中有一个参数,是当前循环的index。相当于for循环中的i
    dispatch_apply(10, dispatch_get_main_queue(), ^(size_t index) {

        // 待执行的任务代码
    });

    // 循环10次,与上面dispatch_apply的调用等价。但是建议使用dispatch_apply模式
    for (int i = 0; i < 10; i++) {

        // 异步分发任务
        dispatch_async(dispatch_get_main_queue(), ^{

            // 待执行的任务代码
        });
    }

2.dispatch_once,函数的声明如下:

void dispatch_once ( dispatch_once_t *predicate, dispatch_block_t block );

这个函数的作用是保证在程序运行生命周期内,分发任务只执行一次。当多线程同时调用此函数时,所有都会被阻塞住,直到分发任务执行完成,然后被阻塞的线程会继续执行。dispatch_once函数的第一个参数用于标识分发任务的执行过程,分发任务是否执行完成都是通过此标识来判断,故此标识必须是一个全局变量或static变量。否则每次都是一个新的标识变量,dispatch_once无法判断分发任务已执行,从而每次调用都会执行分发任务,失去了只需执行一次的意义。

    // 注意,dispatch_once_t是一个static变量
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        // 只需执行一次的代码

    });

dispatch_once一个很大的用处,就是实现单例模式,其能保证代码在程序运行生命周期只执行一次,如果把创建单例的代码放在dispatch_once中执行,则能保证单例创建代码只执行一次,只会创建一个实例。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值