网络请求的任务是提交给子线程异步处理了,对于主线程网络请求这样的任务也就快速执行完毕了,但是对于主线程网络请求是一个任务,处理收到的网络响应又是一个任务,注意不要把这两个过程混为一谈。
我们在进行网络请求的过程中经常会遇到一个场景,就是需要刷新一个界面数据,而这个界面数据需要发起多个请求才能获得,例如:一个用户信息界面,包括基本数据,关联数据,其他特别数据等,这几种数据存在相互依赖的关系,并且获取每种数据的api不同,需要同时异步发起多个请求。在这种场景下面,就需要有一种线程同步机制来处理。通常多线程同步用得最多的就是信号量。不过,直接使用信号量不但代码上面相对松散,还会存在悬挂等问题。GCD已经提供了dispatch_group来很好的实现同步问题。
下面我们就看看这两种方式:
一、GCD的信号量 dispatch_semaphore_t
思路,通过dispatch_group_notify来获取通知,那么必须保证网络请求回调都执行完之后接收到通知,这里是通过dispatch_semaphore来阻塞住group中的任务,直到网络请求返回以后再结束group。
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
dispatch_semaphore_t semaphore1 = dispatch_semaphore_create(0);
//网络请求1
[NetService getUserIconSuccess:^(id successData) {
NSLog(@"----------finished");
dispatch_semaphore_signal(semaphore1);
} error:^(NSString *errorStr) {
NSLog(@"----------finished");
dispatch_semaphore_signal(semaphore1);
}];
dispatch_semaphore_wait(semaphore1, DISPATCH_TIME_FOREVER);
});
dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
dispatch_semaphore_t semaphore2 = dispatch_semaphore_create(0);
//网络请求2
[NetService getUserIconSuccess:^(id successData) {
NSLog(@"----------finished");
dispatch_semaphore_signal(semaphore2);
} error:^(NSString *errorStr) {
NSLog(@"----------finished");
dispatch_semaphore_signal(semaphore2);
}];
dispatch_semaphore_wait(semaphore2, DISPATCH_TIME_FOREVER);
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"两个网络请求都返回了");
});
二、dispatch_group_enter、dispatch_group_leave
- dispatch_group_enter:增加当前group执行block数
- dispatch_group_leave:减少当前group执行block数
相当于通过我们手动调用enter和leave来告诉group中的是否执行结束了,
enter
告诉group增加了一个任务(可以通过引用计数更好理解,+1),leave
告诉group结束了一个任务(-1),当group中没有任务了,就会执行dispatch_group_notify了。
所以,enter和leave
必须成对出现。
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
//网络请求1
[NetService getUserIconSuccess:^(id successData) {
NSLog(@"----------finished");
dispatch_group_leave(group);
} error:^(NSString *errorStr) {
NSLog(@"----------finished");
dispatch_group_leave(group);
}];
dispatch_group_enter(group);
//网络请求2
[NetService getUserIconSuccess:^(id successData) {
NSLog(@"----------finished");
dispatch_group_leave(group);
} error:^(NSString *errorStr) {
NSLog(@"----------finished");
dispatch_group_leave(group);
}];
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"所有网络请求的数据都返回了");
});