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個串行隊列。
兩者的混合使用,完美的解決了控制併發數量,並監聽 所有的請求結束。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章