GCD-Group

group,我所知道的用法,目前有一下两种:

dispatch_group_async(group, queue, ^(){});

我们知道,无论是同步或异步的任务,都需要加到队列中来执行,无论是串行还是并发.
如果是一系列的任务加入到串行队列中,那么很简单,所有的任务都是依次执行的,这样我们很好控制,只需要把需要执行的任务追加到这一系列任务的最后,那么等前面的任务都执行完后,就会执行我们最后追加的任务.
但是如果一系列的异步任务,加入到了一个串行队列里,这些任务都是并行执行,这些任务执行时间长短不一,我们很难去监听这么多个任务的完成情况,这时候,我们该怎么办?
可以使用dispatch_group,顾名思义这是一个组…..
下面我们看一段代码:

void testGroup()
{

    //创建一个group,这里虽然用了create,但是GCD兼容ARC和MRC
    //所以我们这里不需要dispatch_release()
    dispatch_group_t group = dispatch_group_create();
    //这里我们获取一个全局队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //第一个参数是上面创建的组,第二个参数是异步任务要加入的队列,第三个参数就是block,代码块,要执行的代码.
    dispatch_group_async(group, queue, ^(){NSLog(@"block01");});
    dispatch_group_async(group, queue, ^(){NSLog(@"block02");});
    dispatch_group_async(group, queue, ^(){NSLog(@"block03");});    
    /**
     dispatch_group_notify
     @discussion 意思是,监听第一个参数group,如果该group里面的任务全部都完成后,就会调用该方法,在queue中,执行block.
     @param group                   要监听的组
     @param queue 当组结束时,将会把block里的任务提交到该queue中执行,这个参数不能为空.

     @return void
     */
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"block done");
    });
}
/*
输出:
2016-12-29 09:21:23.919 GCD-Group[29814:1253348] block02
2016-12-29 09:21:23.919 GCD-Group[29814:1253493] block01
2016-12-29 09:21:23.919 GCD-Group[29814:1253406] block03
2016-12-29 09:21:23.920 GCD-Group[29814:1253186] block done
*/

你执行时上面的代码时,有可能输出的结果是block01,block02,block03,block done这样的顺序,不过没关系,多运行几下,总会出现顺序颠倒的情况.
想要说的就是block done一定会在上面那三个任务完成之后再进行执行.
因为block01,block02,block03都加入到了group当中,所以只有当group中的所有的任务都执行完毕后,才会去执行dispatch_group_notify后面的代码.

dispatch_group_enter(group);

上面那种用法是书上提到的,那么下面我们看dispatch_group_enter(group)这种用法,这种用法看起来更简单,不过不如上面那种更直观.
因为采用dispatch_group_enter(group)这样的写法,需要在不同的地方,加入到组,并且标记好在什么地方离开组.话不多说,我们看一个实例:

有个场景,比如说,一个界面有两个接口,只有当两个接口都返回数据后,我们才去加载该界面.那么我们该如何去监听者两个网络请求都回来了呢?
难点在于,两个网络请求都是异步的,我们也不清楚它到底什么时候请求成功.我们可以看下如何使用dispatch_group_enter(group)来解决这种问题.

- (void)viewDidLoad {
    [super viewDidLoad];
    //创建组对象,虽然有用到create,但是不用手动release.
    _group = dispatch_group_create();

    //声明下面的第一个方法要加入到组当中.
    dispatch_group_enter(_group);
    //该方法所执行的线程根据上下文来决定的.
    [self requestNews:^(id posts) {
        // code
    }];
    //同上
    dispatch_group_enter(_group);
    [self requestWethear:^(id posts) {
       // code
    }];
    //group里面的所有任务完成后的回调.
    //这个回调对于代码的位置没有固定的要求,放在_group创建的下面也行.
    dispatch_group_notify(_group, dispatch_get_main_queue(), ^{
        NSLog(@"group notify");
    });

}

- (void)requestNews:(void(^)(id posts))success
{
    NSLog(@"requestNews: %@", [NSThread currentThread]);
    success(@{});
    //下面的方法表示任务完成,离开组,如果没有调用,那么将会一直等待该任务的离开
    //如果你没有调用下面的方法,也没有设置dispatch_group_wait
    //那么你的dispatch_group_notify方法里面的block将永远都不会执行.
    //如果该方法没有加入到组里面,但是调用了下面这个方法,那么程序将会崩溃.
    dispatch_group_leave(_group);
}

- (void)requestWethear:(void(^)(id posts))success
{
    success(@{});
    //离开组
    dispatch_group_leave(_group);
}

嗯..就酱.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值