GCD(二)

来源:互联网 发布:网络链接不上 编辑:程序博客网 时间:2024/05/17 04:06

在开发中,我们经常会碰到一类问题,A任务开始执行的前提是B任务执行完成了,针对这种,如果只是简简单单的一个任务接一个任务,可能使用block 嵌套也可以做到,但是如果是C任务开始执行需要等A、B两个异步任务完成,这个呢?这里就需要使用到一些GCD的高级用法。
1、gcd的分组

    //创建分组    dispatch_group_t group = dispatch_group_create();    //创建队列    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);    //往分组中添加任务    dispatch_group_async(group, queue, ^{        [NSThread sleepForTimeInterval:2];//模拟耗时操作        NSLog(@"11111 %@", [NSThread currentThread]);    });    //往分组中添加任务    dispatch_group_async(group, queue, ^{        [NSThread sleepForTimeInterval:1];//模拟耗时操作        NSLog(@"2222 %@", [NSThread currentThread]);    });    //分组中任务完成以后 通知该block 执行    dispatch_group_notify(group, queue, ^{        NSLog(@"完成 %@", [NSThread currentThread]);        dispatch_async(dispatch_get_main_queue(), ^{            NSLog(@"通知主线程刷新UI %@", [NSThread currentThread]);        });    });

执行结果

2017-09-15 11:33:40.426 iOSTest[34497:828682] 2222 <NSThread: 0x600000260080>{number = 3, name = (null)}2017-09-15 11:33:41.426 iOSTest[34497:828660] 11111 <NSThread: 0x608000261d80>{number = 4, name = (null)}2017-09-15 11:33:41.427 iOSTest[34497:828660] 完成 <NSThread: 0x608000261d80>{number = 4, name = (null)}2017-09-15 11:33:41.427 iOSTest[34497:828365] 通知主线程刷新UI <NSThread: 0x60800007b980>{number = 1, name = main}

根据执行结果,可知,使用group可以实现多任务之间的依赖关系,这是直接往group中添加任务,但是有时候,我们的任务一层一层的嵌套了多层Block,这个时候,代码如下:

//创建分组    dispatch_group_t group = dispatch_group_create();    //创建队列    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);    //往分组中添加任务    dispatch_group_async(group, queue, ^{        void (^task)(void) = ^{            [NSThread sleepForTimeInterval:2];//模拟耗时操作            NSLog(@"11111 %@", [NSThread currentThread]);        };        dispatch_async(dispatch_get_global_queue(0, 0), task);        NSLog(@"11111---- %@", [NSThread currentThread]);    });    //往分组中添加任务    dispatch_group_async(group, queue, ^{        void (^task)(void) = ^ {            [NSThread sleepForTimeInterval:1];//模拟耗时操作            NSLog(@"2222 %@", [NSThread currentThread]);        };        dispatch_async(dispatch_get_global_queue(0, 0), task);        NSLog(@"2222------- %@", [NSThread currentThread]);    });    //分组中任务完成以后 通知该block 执行    dispatch_group_notify(group, queue, ^{        NSLog(@"完成 %@", [NSThread currentThread]);        dispatch_async(dispatch_get_main_queue(), ^{            NSLog(@"通知主线程刷新UI %@", [NSThread currentThread]);        });    });

执行结果:

2017-09-15 11:44:06.447 iOSTest[34981:881063] 2222------- <NSThread: 0x610000068000>{number = 4, name = (null)}2017-09-15 11:44:06.447 iOSTest[34981:881046] 11111---- <NSThread: 0x600000071f40>{number = 3, name = (null)}2017-09-15 11:44:06.448 iOSTest[34981:881046] 完成 <NSThread: 0x600000071f40>{number = 3, name = (null)}2017-09-15 11:44:06.450 iOSTest[34981:880987] 通知主线程刷新UI <NSThread: 0x60000006c340>{number = 1, name = main}2017-09-15 11:44:07.450 iOSTest[34981:881064] 2222 <NSThread: 0x6000000708c0>{number = 5, name = (null)}2017-09-15 11:44:08.452 iOSTest[34981:881049] 11111 <NSThread: 0x61000006d5c0>{number = 6, name = (null)}

根据结果我们可以知道,其实刷新主线程的时候,其他两个任务中并没有真正的完成,因为另外两个任务中嵌套了子任务,你就会发现这样执行任务还是不能满足需求,那要怎么做呢?其实group提供了dispatch_group_enter()与dispatch_group_leave()方法来自己组合,但是一定要注意,这两个方法一定需要成对使用,否则会引起莫名Bug。代码如下:

 //创建分组    dispatch_group_t group = dispatch_group_create();    //创建队列    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);    //往分组中添加任务    dispatch_group_enter(group);    dispatch_async(queue, ^{        void (^task)(void) = ^{            [NSThread sleepForTimeInterval:2];//模拟耗时操作            NSLog(@"11111 %@", [NSThread currentThread]);            dispatch_group_leave(group);        };        dispatch_async(dispatch_get_global_queue(0, 0), task);        NSLog(@"11111---- %@", [NSThread currentThread]);    });    //往分组中添加任务    dispatch_group_enter(group);    dispatch_async(queue, ^{        void (^task)(void) = ^ {            [NSThread sleepForTimeInterval:1];//模拟耗时操作            NSLog(@"2222 %@", [NSThread currentThread]);            dispatch_group_leave(group);        };        dispatch_async(dispatch_get_global_queue(0, 0), task);        NSLog(@"2222------- %@", [NSThread currentThread]);    });    //分组中任务完成以后 通知该block 执行    dispatch_group_notify(group, queue, ^{        NSLog(@"完成 %@", [NSThread currentThread]);        dispatch_async(dispatch_get_main_queue(), ^{            NSLog(@"通知主线程刷新UI %@", [NSThread currentThread]);        });    });

执行结果如下:

2017-09-15 11:48:05.641 iOSTest[35128:902591] 11111---- <NSThread: 0x610000073d40>{number = 3, name = (null)}2017-09-15 11:48:05.641 iOSTest[35128:902608] 2222------- <NSThread: 0x60800006fd00>{number = 4, name = (null)}2017-09-15 11:48:06.644 iOSTest[35128:902609] 2222 <NSThread: 0x60000006cb00>{number = 5, name = (null)}2017-09-15 11:48:07.644 iOSTest[35128:902593] 11111 <NSThread: 0x6080000721c0>{number = 6, name = (null)}2017-09-15 11:48:07.644 iOSTest[35128:902593] 完成 <NSThread: 0x6080000721c0>{number = 6, name = (null)}2017-09-15 11:48:07.645 iOSTest[35128:902524] 通知主线程刷新UI <NSThread: 0x61000006e280>{number = 1, name = main}

可以看出,我们想要的结果又回来了。但是这里有个比较重要的地方要注意,这个enter不要放到任务里面了,因为任务是异步执行的,可能会执行执行了下面的完成以后,才执行上面的任务了。

原创粉丝点击