GCD组函数的使用
使用场景:在开发中遇到过这样的功能,某个界面列表上面是资源信息,下面是评论列表信息,而且资源信息和评论列表信息不是同一个接口,必须等两者数据都获取完毕的时候才能刷新UI
1、dispatch_group_t和dispatch_group_async
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
// 1、
dispatch_group_async(group, queue, ^{
[NetworkTool postAlloc:@"http://www.jianshu.com/" parameters:nil successed:^(id json) {
NSLog(@"http://www.jianshu.com/ --- success");
} failure:^(NSError *error) {
NSLog(@"http://www.jianshu.com/ --- failure");
}];
});
// 2、
dispatch_group_async(group, queue, ^{
[NetworkTool postAlloc:@"https://www.baidu.com/" parameters:nil successed:^(id json) {
NSLog(@"https://www.baidu.com/ --- success");
} failure:^(NSError *error) {
NSLog(@"https://www.baidu.com/ --- failure");
}];
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"dispatch_group_notify --- 结束");
});
输出结果
[ViewController.m:278行] dispatch_group_notify --- 结束
[ViewController.m:264行] http://www.jianshu.com/ --- failure
[ViewController.m:271行] https://www.baidu.com/ --- success
说明:这时候问题来了, [NetworkTool postAlloc:parameters:successed:failure]这是封装的请求方法(异步函数),大家都知道,异步函数不会阻塞主线程,不等异步函数执行完毕,dispatch_group_notify里的代码就开始执行了。
解决方法:请看下面的2、和3、实现。
2、dispatch_group_enter和dispatch_group_leave
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
[NetworkTool postAlloc:@"http://www.jianshu.com/" parameters:nil successed:^(id json) {
dispatch_group_leave(group);
NSLog(@"http://www.jianshu.com/ --- success");
} failure:^(NSError *error) {
dispatch_group_leave(group);
NSLog(@"http://www.jianshu.com/ --- failure");
}];
dispatch_group_enter(group);
[NetworkTool postAlloc:@"https://www.baidu.com/" parameters:nil successed:^(id json) {
dispatch_group_leave(group);
NSLog(@"https://www.baidu.com/ --- success");
} failure:^(NSError *error) {
dispatch_group_leave(group);
NSLog(@"https://www.baidu.com/ --- failure");
}];
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"dispatch_group_notify --- 结束");
});
输出结果
[ViewController.m:233行] http://www.jianshu.com/ --- failure
[ViewController.m:239行] https://www.baidu.com/ --- success
[ViewController.m:246行] dispatch_group_notify --- 结束
3、dispatch_group_t、dispatch_group_async和dispatch_semaphore_t结合实现
//使用GCD的信号量 dispatch_semaphore_t 创建同步请求
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
// 1、
dispatch_group_async(group, queue, ^{
dispatch_semaphore_t semaphore= dispatch_semaphore_create(0);
//模拟网络多线程耗时操作
dispatch_group_async(group, queue, ^{
sleep(5);
NSLog(@"%@-->线程1结束。。。",[NSThread currentThread]);
dispatch_semaphore_signal(semaphore);
});
NSLog(@"%@-->1结束。。。",[NSThread currentThread]);
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
});
// 2、
dispatch_group_async(group, queue, ^{
dispatch_semaphore_t semaphore= dispatch_semaphore_create(0);
//模拟网络多线程耗时操作
dispatch_group_async(group, queue, ^{
sleep(3);
NSLog(@"%@-->线程2结束。。。",[NSThread currentThread]);
dispatch_semaphore_signal(semaphore);
});
NSLog(@"%@-->2结束。。。",[NSThread currentThread]);
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
});
dispatch_group_notify(group, queue, ^{
NSLog(@"%@-->全部结束。。。",[NSThread currentThread]);
});
dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{
NSLog(@"%@---全部结束。。。",[NSThread currentThread]);
});
输出结果
[ViewController.m:197行] <NSThread: 0x6000000755c0>{number = 6, name = (null)}-->1结束。。。
[ViewController.m:212行] <NSThread: 0x61000007f6c0>{number = 7, name = (null)}-->2结束。。。
[ViewController.m:208行] <NSThread: 0x608000274dc0>{number = 10, name = (null)}-->线程2结束。。。
[ViewController.m:194行] <NSThread: 0x600000264f40>{number = 11, name = (null)}-->线程1结束。。。
[ViewController.m:217行] <NSThread: 0x6000000755c0>{number = 6, name = (null)}-->全部结束。。。
其他的实现方法有(OSSpinLock 、pthread_mutex_t、NSLock等):
#import <libkern/OSAtomic.h>
//#import <pthread.h>
__block OSSpinLock spinLock = OS_SPINLOCK_INIT;
//__block pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER
//NSLock *lock = [NSLock new];
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
// 1、
dispatch_group_async(group, queue, ^{
//模拟网络多线程耗时操作
OSSpinLockLock(&spinLock);
//pthread_mutex_lock(&mutex);
//[lock lock];
dispatch_group_async(group, queue, ^{
sleep(5);
NSLog(@"%@-->线程1结束。。。",[NSThread currentThread]);
});
NSLog(@"%@-->1结束。。。",[NSThread currentThread]);
OSSpinLockUnlock(&spinLock);
//pthread_mutex_unlock(&mutex);
//[lock unlock];
});
// 2、
dispatch_group_async(group, queue, ^{
OSSpinLockLock(&spinLock);
//模拟网络多线程耗时操作
dispatch_group_async(group, queue, ^{
sleep(3);
NSLog(@"%@-->线程2结束。。。",[NSThread currentThread]);
});
NSLog(@"%@-->2结束。。。",[NSThread currentThread]);
OSSpinLockUnlock(&spinLock);
});
dispatch_group_notify(group, queue, ^{
NSLog(@"%@-->全部结束。。。",[NSThread currentThread]);
});