美文网首页
GCD学习之group

GCD学习之group

作者: 浮生若梦的简书 | 来源:发表于2017-04-20 11:16 被阅读13次

    GCD的group方法只有async(异步方法)即

    void dispatch_group_async(dispatch_group_t group,
        dispatch_queue_t queue,
        dispatch_block_t block);
    

    使用group要传2个参数 group、queue,其中group使用

    //创建group
    dispatch_group_t group = dispatch_group_create();
    

    queue我们可以使用以下几种方式

    dispatch_queue_t queue = dispatch_get_main_queue()
    //或者 
    queue = dispatch_get_global_queue(0, 0);
    //或者 并行队列
    queue = dispatch_queue_create("com.sccc", DISPATCH_QUEUE_CONCURRENT);
    //或者串行队列
    queue = dispatch_queue_create("com.sccc", DISPATCH_QUEUE_SERIAL);
    

    这里主要区分串行和并行的方式

    - (void)doSomething:(void (^)())handler {
        if (handler) {
            sleep(2);
            handler();
        }
    }
    
    //异步串行group
    - (void)groupAsyncSerialTest {
        //创建串行队列
        dispatch_queue_t queue = dispatch_queue_create("com.sccc", DISPATCH_QUEUE_SERIAL);
        dispatch_group_t group = dispatch_group_create();
        
        dispatch_group_async(group, queue, ^{
            [self doSomething:^() {
                NSLog(@"任务一");
            }];
        });
        dispatch_group_async(group, queue, ^{
            [self doSomething:^() {
                NSLog(@"任务二");
            }];
        });
        dispatch_group_async(group, queue, ^{
            [self doSomething:^() {
                NSLog(@"任务三");
            }];
        });
        dispatch_group_notify(group, queue, ^{
            NSLog(@"前面的任务已完成");
        });
    }
    

    结果


    串行队列打印结果

    值得注意的是按照顺序每2s打印一次

    串行队列的情况如下:

    //异步并行
    - (void)groupAsyncConcurrentTest {
        //创建并行队列
        dispatch_queue_t queue = dispatch_queue_create("com.sccc", DISPATCH_QUEUE_CONCURRENT);
        queue = dispatch_get_global_queue(0, 0);
        dispatch_group_t group = dispatch_group_create();
        dispatch_group_async(group, queue, ^{
            [self doSomething:^() {
                NSLog(@"任务一");
            }];
        });
        dispatch_group_async(group, queue, ^{
            [self doSomething:^() {
                NSLog(@"任务二");
            }];
        });
        dispatch_group_async(group, queue, ^{
            [self doSomething:^() {
                NSLog(@"任务三");
            }];
        });
        dispatch_group_notify(group, queue, ^{
            NSLog(@"前面的任务已完成");
        });
    }
    

    结果如下

    并行打印结果

    多次试验总结的结果是任务完成先后顺序不定,前面的任务都完成后才会执行notify中的任务


    当然以上的情况不适用于网络请求
    网络请求使用group时需要注意

    dispatch_group_enter(group);
    dispatch_group_leave(group);
    

    搭配使用
    下面是没有搭配使用的情况

    //异步并行
    - (void)groupAsyncConcurrentTest {
        //创建并行队列
        dispatch_queue_t queue = dispatch_queue_create("com.sccc", DISPATCH_QUEUE_CONCURRENT);
        queue = dispatch_get_global_queue(0, 0);
        dispatch_group_t group = dispatch_group_create();
        dispatch_group_async(group, queue, ^{
            [[CMAppRequest sharedInstance] guideMessage:^() {
               NSLog(@"任务一");
            }];
        });
        dispatch_group_async(group, queue, ^{
            [[CMAppRequest sharedInstance] guideMessage:^() {
                NSLog(@"任务二");
            }];
        });
        dispatch_group_async(group, queue, ^{
            [[CMAppRequest sharedInstance] guideMessage:^() {
                NSLog(@"任务三");
            }];
        });
        dispatch_group_notify(group, queue, ^{
            NSLog(@"前面的任务已完成");
        });
    }
    
    

    结果如下


    网络请求打印结果

    你会发现notify不起作用了,这时候就要用到enter、leave了
    修改代码如下:

    //异步并行
    - (void)groupAsyncConcurrentTest {
        //创建并行队列
        dispatch_queue_t queue = dispatch_queue_create("com.sccc", DISPATCH_QUEUE_CONCURRENT);
        queue = dispatch_get_global_queue(0, 0);
        dispatch_group_t group = dispatch_group_create();
        dispatch_group_enter(group);
        [[CMAppRequest sharedInstance] guideMessage:^() {
               dispatch_group_leave(group);
               NSLog(@"任务一");
        }];
        dispatch_group_enter(group);
        [[CMAppRequest sharedInstance] guideMessage:^() {
                dispatch_group_leave(group);
                NSLog(@"任务二");
        }];
        dispatch_group_enter(group);
        [[CMAppRequest sharedInstance] guideMessage:^() {
                dispatch_group_leave(group);
                NSLog(@"任务三");
        }];
        dispatch_group_notify(group, queue, ^{
            NSLog(@"前面的任务已完成");
        });
    }
    
    //考虑到请求是异步队列,不在需要使用dispatch_group_async
    

    结果如下:


    这就正常了,网络请求的就不在做串行和并行的测试了,以上网络请求部分使用的是串行队列,串行的打印结果只和网络请求的返回顺序有关。

    • 最后特别需要注意,enter和leave一定要成对出现;否则如实enter多了,notify里的任务就会永远执行不了,若是levae多了则会照成crash

    当然这只是group的一部分还有dispatch_group_wait等功能没有一一实现,以上内容只代表个人观点,如有问题欢迎指正,谢谢~~

    相关文章

      网友评论

          本文标题:GCD学习之group

          本文链接:https://www.haomeiwen.com/subject/cvikzttx.html