GCD中dispatch_group详解

       平时在进行多线程处理任务时,有时候希望多个任务之间存在着一种联系,希望在所有的任务执行完后做一些总结性处理。
那么就可以将多个任务放在一个任务组中进行统一管理。通过监听组内所有任务执行情况来做相应处理。

常用函数:

dispatch_group_create():创建一个group组。

dispatch_group_async(group, queue, block):将任务添加到queue队列,并被group组管理。

dispatch_group_enter(group):添加任务组中为执行完毕的任务数,声明dispatch_group_enter(group)下面的任务由group组管理,group组的任务数+1。当未执行完毕任务数为0时,才会使dispatch_group_wait解除阻塞和dispatch_group_notify的block执行,即:通知group,下边的任务要放到group中执行了。

dispatch_group_leave(group):相应的任务执行完成,group组的任务数-1。减少任务组中未执行完毕的任务数,执行一次,未执行完毕的任务数减1,注dispatch_group_enterdispatch_group_leave要匹配,不然系统会认为group任务没有执行完毕。即:通知group,任务完成了,该任务要从group中移除了。

dispatch_group_wait(group, DISPATCH_TIME_FOREVER):在任务完成或超时都会调用;完成是enter和leave一样多),当前线程暂停,等待dispatch_group_wait(group1, DISPATCH_TIME_FOREVER)上面的任务执行完成后,线程才继续执行。dispatch_group_wait 设置等待时间,在等待时间结束后,如果还没有执行完任务组,则返回。返回0代表执行成功,非0则执行失败

dispatch_group_notify(group, queue,block):监听group组中任务的完成状态,当所有的任务都执行完成后,触发block块,执行总结性处理。不管是不是超时,只要任务完成,就会掉,不管是不是超时

注:

1》dispatch_group_enter 和 dispatch_group_leave 一般是成对出现的, 进入一次,就得离开一次。也就是说,当离开和进入的次数相同时,就代表任务组完成了。如果enter比leave多,那就是没完成,会阻塞当前线程,如果leave调用的次数错了, 会崩溃;这两个方法显示的讲任务组中的任务未执行完毕的任务数目加减1,这种方式用在不使用dispatch_group_async来提交任务,注意:这两个函数要配合使用,有enter要有leave,这样才能保证功能完整实现。也可以用这对函数来让一个闭包关联多个Group。

2》dispatch_group_wait和dispatch_group_notify可以监听任务组内任务的执行情况。监听group组中任务的完成状态,当所有的任务都执行完成后,触发block块,执行总结性处理。

作用:

需要开启多个线程执行任务,例如有5张以下加入是3张图片需要异步下载,等3张图片下载完后需要合并成一张图片的操作,需要group。(这里为么说是5张以下呢,因为开线程需要消耗cpu,开太多会造成卡顿等现象,最多开五条线程,如果下载的图片很多,例如100张,那我们就要用信号量dispatch_semaphore 来调度任务和线程

分析:因为需要合并成一张图片,所以必须等三张图片全下载完才能执行合并操作,所以需要用到dispatch_group来对下载情况做处理。

使用:group使用的时候一般有两种组合形式:

1》dispatch_group_async方式:

       dispatch_group_async(group, queue, block); //将任务添加到queue队列,并由group管理

       dispatch_group_notify(group, queue, block);

2》enter与leave方式:     

      dispatch_group_enter(group);//将下边的任务由group管理

      dispatch_group_leave(group);//任务完成,将任务从group移除

      dispatch_group_notify(group, queue,block);

方式一:

    

{

    dispatch_group_t asyncAsyncGroup = dispatch_group_create();

    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);

    dispatch_group_async(asyncAsyncGroup, queue, ^{

        dispatch_async(queue, ^{

            sleep(10);

            NSLog(@"第一个任务");

        });

    });

    dispatch_group_async(asyncAsyncGroup, queue, ^{

        dispatch_async(queue, ^{

            sleep(1);

            NSLog(@"第二个任务");

        });

    });

    dispatch_group_notify(asyncAsyncGroup, queue, ^{

        NSLog(@"执行完毕了");

    });

}

打印:

2018-10-18 16:56:23.501176+0800 dispatch_group[50937:2436276] 执行完毕了

2018-10-18 16:56:24.501235+0800 dispatch_group[50937:2436278] 第二个任务

2018-10-18 16:56:33.501669+0800 dispatch_group[50937:2436277] 第一个任务

方式二:

{

    dispatch_group_t group = dispatch_group_create();

//    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);

    

    dispatch_group_enter(group);

    dispatch_async(dispatch_get_global_queue(0, 0), ^{

        dispatch_async(dispatch_get_global_queue(0, 0), ^{

            sleep(3);

            NSLog(@"子线程中的子线程1");

            dispatch_group_leave(group);

        });

    });

    

    dispatch_group_enter(group);

    dispatch_async(dispatch_get_global_queue(0, 0), ^{

        dispatch_async(dispatch_get_global_queue(0, 0), ^{

            sleep(2);

            NSLog(@"子线程中的子线程2");

            dispatch_group_leave(group);

        });

    });

    

    dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{

        NSLog(@"所有线程执行完毕");

    });

    

}

打印:

2018-10-18 16:57:56.250547+0800 dispatch_group[50968:2438605] 子线程中的子线程2

2018-10-18 16:57:57.250830+0800 dispatch_group[50968:2438607] 子线程中的子线程1

2018-10-18 16:57:57.251054+0800 dispatch_group[50968:2438607] 所有线程执行完毕

以上两种方式都是模拟任务block内为异步操作的情况,方式一先执行的dispatch_group_notify里的代码,后执行的dispatch_group_async里的任务代码,这与我们的初衷相违背。如果任务block内为同步操作时,则无论哪种方式都不会出现这种状况。这也是dispatch_group的一个坑人的地方。我们在使用dispatch_group时一般都是想异步执行任务,所以,一定要注意这个坑

另外,还有dispatch_group_wait的使用,也提现在代码里了,可以任意修改wai里的时间,例如小于任务一的睡眠时间,大于任务一+任务二的睡眠时间总和,查看打印的变化,理解wait的作用。

代码:https://download.csdn.net/download/denggun12345/10730166

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值