1. 程式人生 > >IOS-如何處理多個網路請求的併發的情況

IOS-如何處理多個網路請求的併發的情況

如何處理多個網路請求的併發的情況

一、概念

1.併發 當有多個執行緒在操作時,如果系統只有一個CPU,則它根本不可能真正同時進行一個以上的執行緒,它只能把CPU執行時間劃分成若干個時間段,再將時間 段分配給各個執行緒執行,在一個時間段的執行緒程式碼執行時,其它執行緒處於掛起狀。.這種方式我們稱之為併發(Concurrent)。

2.並行 當系統有一個以上CPU時,則執行緒的操作有可能非併發。當一個CPU執行一個執行緒時,另一個CPU可以執行另一個執行緒,兩個執行緒互不搶佔CPU資源,可以同時進行,這種方式我們稱之為並行(Parallel)。

3.區別 併發和並行是即相似又有區別的兩個概念,並行是指兩個或者多個事件在同一時刻發生;而併發是指兩個或多個事件在同一時間間隔內發生。

舉個例子:
1).併發 一個送外賣的A需要把兩份外賣分別送到兩個客戶B和C手裡。 A必須先送完B外賣才能接著送C的。這就是併發

2).並行 客戶C 分別從餓了麼和美團訂了一共兩份外賣。那麼外賣員A和外賣員B需要把外賣一同送到客戶C手裡。 這就是並行

  在iOS中,經常可以看見有這樣的需求,就是一個方法要等另外一個方法執行完畢再做相對應的處理,比如說一些網路請求,需要根據上一個請求的返回值做相對應的處理再執行第二個請求,所以我們不能讓兩個請求同時去請求網路。下面就記錄以下通過GCD和NSOperationQueue來控制併發。

二、程式碼部分(GCD)

dispatch_semaphore 訊號量

訊號量是一個整型值並且具有初始計數值,訊號量通常支援兩個操作:通知和等待。當訊號被通知的時候計數值會增加,當訊號量線上程上等待的時候,必要的情況下執行緒會被阻塞掉,直至訊號被通知時計數值大於0,然後執行緒會減少這個計數繼續工作。

GCD中又3個訊號量有關的操作:

dispatch_semaphore_create    訊號量建立

dispatch_semaphore_signal    傳送通知

dispatch_semaphore_wait     訊號量等待

GCD

 #import <Foundation/Foundation.h>
 2 
 3  int main(int
argc, const char * argv[]) { 4 5 @autoreleasepool { 6 7 // 建立訊號量 8 9 __block dispatch_semaphore_t sem = dispatch_semaphore_create(0); 10 11 // 建立佇列 12 13 dispatch_queue_t queue = dispatch_queue_create("testBlock", NULL); 14 15 dispatch_async(queue, ^{ 16 17 for (int i = 0; i<10; i++) { 18 19 NSLog(@"i的值是:%d",i); 20 21 } 22 23 // 傳送通知 24 25 dispatch_semaphore_signal(sem); 26 27 }); 28 29 30 31 // 訊號量等待 32 33 dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); 34 35 36 37 for (int j = 0; j<20; j++) { 38 39 NSLog(@"j的值是:%d",j); 40 41 } 42 43 } 44 45 return 0; 46

列印結果為

2016-12-19 13:17:04.195 多執行緒[16370:1833932] i的值是:0
2016-12-19 13:17:04.197 多執行緒[16370:1833932] i的值是:1
2016-12-19 13:17:04.197 多執行緒[16370:1833932] i的值是:2
2016-12-19 13:17:04.197 多執行緒[16370:1833932] i的值是:3
2016-12-19 13:17:04.197 多執行緒[16370:1833932] i的值是:4
2016-12-19 13:17:04.198 多執行緒[16370:1833932] i的值是:5
2016-12-19 13:17:04.198 多執行緒[16370:1833932] i的值是:6
2016-12-19 13:17:04.198 多執行緒[16370:1833932] i的值是:7
2016-12-19 13:17:04.198 多執行緒[16370:1833932] i的值是:8
2016-12-19 13:17:04.198 多執行緒[16370:1833932] i的值是:9
2016-12-19 13:17:04.198 多執行緒[16370:1833932] j的值是:0
2016-12-19 13:17:04.199 多執行緒[16370:1833932] j的值是:1
2016-12-19 13:17:04.199 多執行緒[16370:1833932] j的值是:2
2016-12-19 13:17:04.199 多執行緒[16370:1833932] j的值是:3
2016-12-19 13:17:04.199 多執行緒[16370:1833932] j的值是:4
2016-12-19 13:17:04.199 多執行緒[16370:1833932] j的值是:5
2016-12-19 13:17:04.199 多執行緒[16370:1833932] j的值是:6
2016-12-19 13:17:04.199 多執行緒[16370:1833932] j的值是:7
2016-12-19 13:17:04.221 多執行緒[16370:1833932] j的值是:8
2016-12-19 13:17:04.221 多執行緒[16370:1833932] j的值是:9
2016-12-19 13:17:04.222 多執行緒[16370:1833932] j的值是:10
2016-12-19 13:17:04.222 多執行緒[16370:1833932] j的值是:11
2016-12-19 13:17:04.222 多執行緒[16370:1833932] j的值是:12
2016-12-19 13:17:04.222 多執行緒[16370:1833932] j的值是:13
2016-12-19 13:17:04.222 多執行緒[16370:1833932] j的值是:14
2016-12-19 13:17:04.222 多執行緒[16370:1833932] j的值是:15
2016-12-19 13:17:04.222 多執行緒[16370:1833932] j的值是:16
2016-12-19 13:17:04.223 多執行緒[16370:1833932] j的值是:17
2016-12-19 13:17:04.223 多執行緒[16370:1833932] j的值是:18
2016-12-19 13:17:04.223 多執行緒[16370:1833932] j的值是:19

我們看到先列印完i值後在列印j值 這就完成了併發請求

NSOperationQueue

-(void)viewDidLoad {
    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

    // 建立一個佇列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init]; 

    // 設定最大執行緒數
    queue.maxConcurrentOperationCount = 5;

    // 建立一個A操作
    NSBlockOperation *operationA = [NSBlockOperation blockOperationWithBlock:^{

        for (int i = 0; i<10; i++) {
            NSLog(@"i的值是:%d",i);
        }
    }];

    // 建立一個B操作
    NSBlockOperation *operationB = [NSBlockOperation blockOperationWithBlock:^{
        for (int j = 0; j<20; j++) {
            NSLog(@"j的值是:%d",j);
        }
    }];

    // 分別加入到佇列中
    [queue addOperation:operationA];
    [queue addOperation:operationB];
}

列印結果

2016-12-19 13:56:04.508 111[16598:1880752] j的值是:0
2016-12-19 13:56:04.508 111[16598:1880750] i的值是:0
2016-12-19 13:56:04.509 111[16598:1880752] j的值是:1
2016-12-19 13:56:04.509 111[16598:1880750] i的值是:1
2016-12-19 13:56:04.509 111[16598:1880752] j的值是:2
2016-12-19 13:56:04.509 111[16598:1880750] i的值是:2
2015-07-28 17:51:09.509 111[16598:1880752] j的值是:3
2016-12-19 13:56:04.509 111[16598:1880750] i的值是:3
2016-12-19 13:56:04.509 111[16598:1880752] j的值是:4
2016-12-19 13:56:04.509 111[16598:1880750] i的值是:4
2016-12-19 13:56:04.509 111[16598:1880752] j的值是:5
2016-12-19 13:56:04.509 111[16598:1880750] i的值是:5
2016-12-19 13:56:04.509 111[16598:1880752] j的值是:6
2016-12-19 13:56:04.509 111[16598:1880750] i的值是:6
2016-12-19 13:56:04.509 111[16598:1880752] j的值是:7
2016-12-19 13:56:04.509 111[16598:1880750] i的值是:7
2016-12-19 13:56:04.509 111[16598:1880752] j的值是:8
2016-12-19 13:56:04.509 111[16598:1880750] i的值是:8
2016-12-19 13:56:04.510 111[16598:1880752] j的值是:9
2016-12-19 13:56:04.510 111[16598:1880750] i的值是:9

我們看到列印順序是交替進行的。 那麼如何進行順序操作呢。只需一行程式碼。

- (void)viewDidLoad {

    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.
    // 建立一個佇列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];

    // 設定最大執行緒數
    queue.maxConcurrentOperationCount = 5;

    // 建立一個A操作
    NSBlockOperation *operationA = [NSBlockOperation blockOperationWithBlock:^{

        for (int i = 0; i<10; i++) {

            NSLog(@"i的值是:%d",i); 
        }
    }];

    // 建立一個B操作
    NSBlockOperation *operationB = [NSBlockOperation blockOperationWithBlock:^{

        for (int j = 0; j<20; j++) {
            NSLog(@"j的值是:%d",j);
        }
    }];

 // 新增依賴 B要在A列印完在進行列印 所以是B依賴於A 那麼只需要新增如下程式碼即可完成

  [operationB addDependency:operationA];

    // 分別加入到佇列中
    [queue addOperation:operationA];
    [queue addOperation:operationB];
}

列印結果

2016-12-19 13:58:02.606 111[16625:1882738] i的值是:0
2016-12-19 13:58:02.609 111[16625:1882738] i的值是:1
2016-12-19 13:58:02.609 111[16625:1882738] i的值是:2
2016-12-19 13:58:02.609 111[16625:1882738] i的值是:3
2016-12-19 13:58:02.609 111[16625:1882738] i的值是:4
2016-12-19 13:58:02.609 111[16625:1882738] i的值是:5
2016-12-19 13:58:02.609 111[16625:1882738] i的值是:6
2016-12-19 13:58:02.609 111[16625:1882738] i的值是:7
2016-12-19 13:58:02.610 111[16625:1882738] i的值是:8
2016-12-19 13:58:02.610 111[16625:1882738] i的值是:9
2016-12-19 13:58:02.610 111[16625:1882738] j的值是:0
2016-12-19 13:58:02.610 111[16625:1882738] j的值是:1
2016-12-19 13:58:02.610 111[16625:1882738] j的值是:2
2016-12-19 13:58:02.610 111[16625:1882738] j的值是:3
2016-12-19 13:58:02.610 111[16625:1882738] j的值是:4
2016-12-19 13:58:02.611 111[16625:1882738] j的值是:5
2016-12-19 13:58:02.611 111[16625:1882738] j的值是:6
2016-12-19 13:58:02.611 111[16625:1882738] j的值是:7
2016-12-19 13:58:02.611 111[16625:1882738] j的值是:8
2016-12-19 13:58:02.611 111[16625:1882738] j的值是:9

順序操作請求完成。