*前言:最近写的app需要综合用到api的串行和并行, 所以整理了下使用的api的情况。
主要用到的GCD方法:dispatch_group_leave
, dispatch_group_enter
, 以及semaphore
的运用。*
code:
- (void)test {
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
NSLog(@"请求开始");
dispatch_group_async(group, queue, ^{
for (int i = 0; i < 4; i++) {
NSLog(@"----------开始请求 i = %i", i);
//随便请求都行
[BYNetPort requestFileSettingsSuccess:^(id responseObject) {
NSLog(@"--------成功 i = %i",i);
dispatch_semaphore_signal(semaphore);
} failure:^(NSError *error) {
NSLog(@"--------成功 i = %i",i);
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
});
dispatch_group_notify(group, queue, ^{
NSLog(@"----全部请求完毕---");
});
}
以下是输出结果:
2018-09-07 15:37:46.567017+0800 kantan[32591:12521747] 请求开始
2018-09-07 15:37:46.567213+0800 kantan[32591:12521836] ----------开始请求 i = 0
2018-09-07 15:37:47.123672+0800 kantan[32591:12521747] --------成功 i = 0
2018-09-07 15:37:47.123853+0800 kantan[32591:12521836] ----------开始请求 i = 1
2018-09-07 15:37:47.622304+0800 kantan[32591:12521747] --------成功 i = 1
2018-09-07 15:37:47.622575+0800 kantan[32591:12521836] ----------开始请求 i = 2
2018-09-07 15:37:48.648025+0800 kantan[32591:12521747] --------成功 i = 2
2018-09-07 15:37:48.648289+0800 kantan[32591:12521836] ----------开始请求 i = 3
2018-09-07 15:37:49.216007+0800 kantan[32591:12521747] --------成功 i = 3
2018-09-07 15:37:49.216195+0800 kantan[32591:12521836] ----全部请求完毕---
小结: 使用信号量由三组函数构成: dispatch_semaphore_create
,dispatch_semaphore_signal
,dispatch_semaphore_wait
。注意当dispatch_semaphore_create
函数的值传为0的时候,为串行顺序的执行, 当值 >0 的时候,为并行队列,但是需要配合第二节 enter
和leave
使用, 不然会当数据还未请求完成时,便进入dispatch_group_notify
方法。
比如将dispatch_semaphore_create
的参数变为 2
, 会出现以下打印结果。注意会当数据还未请求完成时,便进入dispatch_group_notify
方法
2018-09-07 15:50:08.531976+0800 kantan[32903:12533391] 请求开始
2018-09-07 15:50:08.532385+0800 kantan[32903:12533484] ----------开始请求 i = 0
2018-09-07 15:50:08.543797+0800 kantan[32903:12533484] ----------开始请求 i = 1
2018-09-07 15:50:08.548670+0800 kantan[32903:12533484] ----------开始请求 i = 2
2018-09-07 15:50:09.111805+0800 kantan[32903:12533391] --------成功 i = 1
2018-09-07 15:50:09.112008+0800 kantan[32903:12533484] ----------开始请求 i = 3
2018-09-07 15:50:09.112148+0800 kantan[32903:12533391] --------成功 i = 2
2018-09-07 15:50:09.113628+0800 kantan[32903:12533391] --------成功 i = 0
2018-09-07 15:50:09.113659+0800 kantan[32903:12533484] ----全部请求完毕---
2018-09-07 15:50:09.646332+0800 kantan[32903:12533391] --------成功 i = 3
code:
- (void)test {
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSLog(@"请求开始");
dispatch_group_async(group, queue, ^{
for (int i = 0; i < 4; i++) {
NSLog(@"----------开始请求 i = %i", i);
//随便请求都行
[BYNetPort requestFileSettingsSuccess:^(id responseObject) {
NSLog(@"--------成功 i = %i",i);
dispatch_group_leave(group);
} failure:^(NSError *error) {
NSLog(@"--------成功 i = %i",i);
dispatch_group_leave(group);
}];
dispatch_group_enter(group);
}
});
dispatch_group_notify(group, queue, ^{
NSLog(@"----全部请求完毕---");
});
}
以下是输出结果:
2018-09-07 15:43:24.538455+0800 kantan[32746:12527236] 请求开始
2018-09-07 15:43:24.538653+0800 kantan[32746:12527354] ----------开始请求 i = 0
2018-09-07 15:43:24.548369+0800 kantan[32746:12527354] ----------开始请求 i = 1
2018-09-07 15:43:24.549534+0800 kantan[32746:12527354] ----------开始请求 i = 2
2018-09-07 15:43:24.550806+0800 kantan[32746:12527354] ----------开始请求 i = 3
2018-09-07 15:43:25.064171+0800 kantan[32746:12527236] --------成功 i = 0
2018-09-07 15:43:25.145752+0800 kantan[32746:12527236] --------成功 i = 2
2018-09-07 15:43:25.146124+0800 kantan[32746:12527236] --------成功 i = 1
2018-09-07 15:43:25.155443+0800 kantan[32746:12527236] --------成功 i = 3
2018-09-07 15:43:25.155616+0800 kantan[32746:12527348] ----全部请求完毕---
小结:单纯使用dispatch_group_enter
和 dispatch_group_leave
控制并行队列。 虽然可以在所有队列请求结束后进入dispatch_group_notify
方法。 但是还有个问题是 不能控制同时并发数,如果for循环的i为1000, 那么会并行1000个线程。 如果对并行线程数没有要求的可以考虑此方法。
code:
- (void)test {
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
NSLog(@"请求开始");
dispatch_group_async(group, queue, ^{
for (int i = 0; i < 6; i++) {
NSLog(@"----------开始请求 i = %i", i);
//随便请求都行
[BYNetPort requestFileSettingsSuccess:^(id responseObject) {
NSLog(@"--------成功 i = %i",i);
dispatch_group_leave(group);
dispatch_semaphore_signal(semaphore);
} failure:^(NSError *error) {
NSLog(@"--------成功 i = %i",i);
dispatch_group_leave(group);
dispatch_semaphore_signal(semaphore);
}];
dispatch_group_enter(group);
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
});
dispatch_group_notify(group, queue, ^{
NSLog(@"----全部请求完毕---");
});
}
以下是输出结果:
2018-09-07 15:56:58.368120+0800 kantan[33065:12539726] 请求开始
2018-09-07 15:56:58.368321+0800 kantan[33065:12539783] ----------开始请求 i = 0
2018-09-07 15:56:58.392233+0800 kantan[33065:12539783] ----------开始请求 i = 1
2018-09-07 15:56:58.394367+0800 kantan[33065:12539783] ----------开始请求 i = 2
2018-09-07 15:56:58.912951+0800 kantan[33065:12539726] --------成功 i = 0
2018-09-07 15:56:58.915470+0800 kantan[33065:12539783] ----------开始请求 i = 3
2018-09-07 15:56:58.957665+0800 kantan[33065:12539726] --------成功 i = 2
2018-09-07 15:56:58.957837+0800 kantan[33065:12539783] ----------开始请求 i = 4
2018-09-07 15:56:58.979873+0800 kantan[33065:12539726] --------成功 i = 1
2018-09-07 15:56:58.980089+0800 kantan[33065:12539783] ----------开始请求 i = 5
2018-09-07 15:56:59.418535+0800 kantan[33065:12539726] --------成功 i = 3
2018-09-07 15:56:59.480643+0800 kantan[33065:12539726] --------成功 i = 4
2018-09-07 15:56:59.495432+0800 kantan[33065:12539726] --------成功 i = 5
2018-09-07 15:56:59.495599+0800 kantan[33065:12539786] ----全部请求完毕---
小结: 注意信号量的初始值传的是2. 所以我们最多同开辟3个串行队列。
两者的混合使用,完美的解决了控制并发数量,并监听 所有的请求结束。