GCD 之四:Dispatch Group
2014-04-07 18:39
134 查看
在追加到Dispatch Queue中的多个处理全部结束后想执行结束处理,这种情况会经常出现。只使用一个Serial Dispatch Queue时,只要将想执行的处理全部追加到该Serial Dispatch Queue中并在最后追加结束处理,即可实现。但是在使用Concurrent Dispatch Queue时或同时使用多个Dispatch Queue时,源代码就会变得颇为复杂。
在此种情况下使用Dispatch Group。例如下面源代码为:追加3个Block到Global Dispatch Queue,这些Block如果全部执行完毕,就会执行Main Dispatch Queue中结束处理用的Block。
源代码的执行结果如下:
因为向Global Dispatch Queue即Concurrent Dispatch Queue追加处理,多个线程并行执行,所以追加处理的执行顺序不定。执行时会发生变化,但是此执行结果的done一定是最后输出的。
无论向什么样的Dispatch Queue中追加处理,使用Dispatch Group都可监视这些处理执行的结束。一旦检测到所有处理执行结束,就可将结束的处理追加到Dispatch Queue中。这就是使用Dispatch Queue的原因。
首先dispatch_group_create函数生成dispatch_group_t类型的Dispatch Group。如dispatch_group_create函数名中所含的create所示,该Dispatch Group与Dispatch Queue相同,在使用结束后需要通过dispatch_release函数释放。
dispatch_group_async函数与dispatch_async函数相同,Block通过dispatch_retain函数持有Dispatch Group,从而使得该Block属于Dispatch Group。这样如果Block执行结束,该Block就通过dispatch_release函数释放持有的Dispatch Group。一旦Dispatch Group使用结束,不用考虑属于该Dispatch Group的Block,立即通过dispatch_release函数释放即可。
在追加到Dispatch Group中的处理全部执行结束时,该源代码中使用的dispatch_group_notify函数会将执行的Block追加到Dispatch Queue中,将第一个参数指定为要监视的Dispatch Group。在追加到该Dispatch Group的全部处理执行结束时,将第三个参数的Block追加到第二个参数的Dispatch Queue中。在dispatch_group_notify函数中不管指定什么样的Dispatch Queue,属于Dispatch Group的全部处理在追加指定的Block时都已执行结束。
另外,在Dispatch Group中也可以使用dispatch_group_wait函数公等待全部处理执行结束。
dispatch_group_wait函数的第二个参数指定为等待的时间(超时)。它属于dispatch_time_t类型的值。该源代码使用DISPATCH_TIME_FOREVER,意味着永久等待。只要属于Dispatch Group的处理尚未执行结束,就会一直等待,中途不能取消。
指定等待间隔为1秒时可做如下处理:
如果dispatch_group_wait函数的返回值不为0,就意味着虽然经过了指定的时间,但属于Dispatch Group的某一个处理还在执行中。如果返回值为0,那么全部处理执行结束。当等待时间为DISPATCH_TIME_FOREVER、由dispatch_group_wait函数返回时,由于属于Dispatch Group的处理必定全部执行结束,因此返回值恒为0.
这里的“等待”是什么意思呢?这意味着一旦调用dispatch_group_wait函数,该函数就牌调用的状态而不返回。即执行dispatch_group_wait函数的现在的线程(当前线程)停止。在经过dispatch_group_wait函数中的时间或属于指定Dispatch Group的处理全部执行结束之前,执行该函数的线程停止。
指定DISPATCH_TIME_NOW,则不用任何等待即可判定属于Dispatch Group的处理是否执行结束。
在主线程的RunLoop的每次循环中,中检查执行是否结束,从而不耗费多余的等待时间,虽然这样也可以,但一般在这种情况下,还是推荐用dispatch_group_notify函数追加到结束处理到Main Dispatch Queue中,因为dispatch_group_notify函数可以简化源代码。
在此种情况下使用Dispatch Group。例如下面源代码为:追加3个Block到Global Dispatch Queue,这些Block如果全部执行完毕,就会执行Main Dispatch Queue中结束处理用的Block。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, queue, ^{NSLog(@"block0");}); dispatch_group_async(group, queue, ^{NSLog(@"block1");}); dispatch_group_async(group, queue, ^{NSLog(@"block2");}); dispatch_group_notify(group, dispatch_get_main_queue(), ^{NSLog(@"done");}); dispatch_release(group);
源代码的执行结果如下:
block0 block2 block1 done
因为向Global Dispatch Queue即Concurrent Dispatch Queue追加处理,多个线程并行执行,所以追加处理的执行顺序不定。执行时会发生变化,但是此执行结果的done一定是最后输出的。
无论向什么样的Dispatch Queue中追加处理,使用Dispatch Group都可监视这些处理执行的结束。一旦检测到所有处理执行结束,就可将结束的处理追加到Dispatch Queue中。这就是使用Dispatch Queue的原因。
首先dispatch_group_create函数生成dispatch_group_t类型的Dispatch Group。如dispatch_group_create函数名中所含的create所示,该Dispatch Group与Dispatch Queue相同,在使用结束后需要通过dispatch_release函数释放。
dispatch_group_async函数与dispatch_async函数相同,Block通过dispatch_retain函数持有Dispatch Group,从而使得该Block属于Dispatch Group。这样如果Block执行结束,该Block就通过dispatch_release函数释放持有的Dispatch Group。一旦Dispatch Group使用结束,不用考虑属于该Dispatch Group的Block,立即通过dispatch_release函数释放即可。
在追加到Dispatch Group中的处理全部执行结束时,该源代码中使用的dispatch_group_notify函数会将执行的Block追加到Dispatch Queue中,将第一个参数指定为要监视的Dispatch Group。在追加到该Dispatch Group的全部处理执行结束时,将第三个参数的Block追加到第二个参数的Dispatch Queue中。在dispatch_group_notify函数中不管指定什么样的Dispatch Queue,属于Dispatch Group的全部处理在追加指定的Block时都已执行结束。
另外,在Dispatch Group中也可以使用dispatch_group_wait函数公等待全部处理执行结束。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, queue, ^{NSLog(@"block0");}); dispatch_group_async(group, queue, ^{NSLog(@"block1");}); dispatch_group_async(group, queue, ^{NSLog(@"block2");}); dispatch_group_wait(group, DISPATCH_TIME_FOREVER); dispatch_release(group);
dispatch_group_wait函数的第二个参数指定为等待的时间(超时)。它属于dispatch_time_t类型的值。该源代码使用DISPATCH_TIME_FOREVER,意味着永久等待。只要属于Dispatch Group的处理尚未执行结束,就会一直等待,中途不能取消。
指定等待间隔为1秒时可做如下处理:
dispatch_time_time time = dispatch_time(DISPATCH_TIME_NOW, 1ull * NSEC_PER_SEC); long result = dispatch_group_wait(group, time); if (result == 0) { /* * 属于Dispatch Group的全部处理执行结束 */ } else { /* * 属于Dispatch Group的某一个处理还在执行中 */ }
如果dispatch_group_wait函数的返回值不为0,就意味着虽然经过了指定的时间,但属于Dispatch Group的某一个处理还在执行中。如果返回值为0,那么全部处理执行结束。当等待时间为DISPATCH_TIME_FOREVER、由dispatch_group_wait函数返回时,由于属于Dispatch Group的处理必定全部执行结束,因此返回值恒为0.
这里的“等待”是什么意思呢?这意味着一旦调用dispatch_group_wait函数,该函数就牌调用的状态而不返回。即执行dispatch_group_wait函数的现在的线程(当前线程)停止。在经过dispatch_group_wait函数中的时间或属于指定Dispatch Group的处理全部执行结束之前,执行该函数的线程停止。
指定DISPATCH_TIME_NOW,则不用任何等待即可判定属于Dispatch Group的处理是否执行结束。
long result = dispatch_group_wait(group, DISPATCH_TIME_NOW);
在主线程的RunLoop的每次循环中,中检查执行是否结束,从而不耗费多余的等待时间,虽然这样也可以,但一般在这种情况下,还是推荐用dispatch_group_notify函数追加到结束处理到Main Dispatch Queue中,因为dispatch_group_notify函数可以简化源代码。
相关文章推荐
- GCD收录3--dispatch_group线程调度组
- GCD 学习(四) dispatch_group
- GCD 信号量控制并发(dispatch_semaphore)以及dispatch_group_async
- iOS--GCD(使用dispatch_group来进行线程同步)
- 完整详解GCD系列(三)dispatch_group
- iOS GCD中级篇 - dispatch_group的理解及使用
- GCD高级用法(二) dispatch_group
- 完整详解GCD系列(三)dispatch_group
- iOS系统GCD学习(3):dispatch_group
- iOS GCD之dispatch_group的使用(多个文件并发上传)
- iOS系统GCD学习(4):dispatch_group2
- iOS系统GCD学习(3):dispatch_group
- GCD(dispatch_group)
- GCD 第三篇 dispatch_group
- iOS学习笔记74- 完整详解GCD系列(三)dispatch_group
- GCD(三) ---- dispatch_group 调度群组
- iOS开发:深入理解GCD 第二篇(dispatch_group、dispatch_barrier、基于线程安全的多读单写)
- GCD学习笔记(六):Dispatch Group
- iOS系统GCD学习(4):dispatch_group2
- GCD使用dispatch_group_notify、dispatch_group_enter、dispatch_group_leave处理多线程同步操作