ios GCD的实际串行和并行请求api调用

*前言:最近写的app需要综合用到api的串行和并行, 所以整理了下使用的api的情况。
主要用到的GCD方法:dispatch_group_leavedispatch_group_enter, 以及semaphore的运用。*


1. 信号量串行顺序请求。(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_createdispatch_semaphore_signaldispatch_semaphore_wait。注意当dispatch_semaphore_create函数的值传为0的时候,为串行顺序的执行, 当值 >0 的时候,为并行队列,但是需要配合第二节 enterleave使用, 不然会当数据还未请求完成时,便进入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

2.并行请求 group leave 和 enter ##

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_enterdispatch_group_leave 控制并行队列。 虽然可以在所有队列请求结束后进入dispatch_group_notify方法。 但是还有个问题是 不能控制同时并发数,如果for循环的i为1000, 那么会并行1000个线程。 如果对并行线程数没有要求的可以考虑此方法。


3. group和信号量混合使用,控制同时并发数

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个串行队列。
两者的混合使用,完美的解决了控制并发数量,并监听 所有的请求结束。

你可能感兴趣的:(iOS)