如何處理多個(gè)網(wǎng)絡(luò)請(qǐng)求的并發(fā)的情況

一、概念

1.并發(fā)?當(dāng)有多個(gè)線程在操作時(shí),如果系統(tǒng)只有一個(gè)CPU,則它根本不可能真正同時(shí)進(jìn)行一個(gè)以上的線程,它只能把CPU運(yùn)行時(shí)間劃分成若干個(gè)時(shí)間段,再將時(shí)間 段分配給各個(gè)線程執(zhí)行,在一個(gè)時(shí)間段的線程代碼運(yùn)行時(shí),其它線程處于掛起狀。.這種方式我們稱之為并發(fā)(Concurrent)。

2.并行?當(dāng)系統(tǒng)有一個(gè)以上CPU時(shí),則線程的操作有可能非并發(fā)。當(dāng)一個(gè)CPU執(zhí)行一個(gè)線程時(shí),另一個(gè)CPU可以執(zhí)行另一個(gè)線程,兩個(gè)線程互不搶占CPU資源,可以同時(shí)進(jìn)行,這種方式我們稱之為并行(Parallel)。

3.區(qū)別?并發(fā)和并行是即相似又有區(qū)別的兩個(gè)概念,并行是指兩個(gè)或者多個(gè)事件在同一時(shí)刻發(fā)生;而并發(fā)是指兩個(gè)或多個(gè)事件在同一時(shí)間間隔內(nèi)發(fā)生。

舉個(gè)栗子

1).并發(fā) 一個(gè)送外賣的A需要把兩份外賣分別送到兩個(gè)客戶B和C手里。 A必須先送完B外賣才能接著送C的。這就是并發(fā)

2).并行 客戶C 分別從餓了么和美團(tuán)訂了一共兩份外賣。那么外賣員A和外賣員B需要把外賣一同送到客戶C手里。 這就是并行

在iOS中,經(jīng)常可以看見有這樣的需求,就是一個(gè)方法要等另外一個(gè)方法執(zhí)行完畢再做相對(duì)應(yīng)的處理,比如說一些網(wǎng)絡(luò)請(qǐng)求,需要根據(jù)上一個(gè)請(qǐng)求的返回值做相對(duì)應(yīng)的處理再執(zhí)行第二個(gè)請(qǐng)求,所以我們不能讓兩個(gè)請(qǐng)求同時(shí)去請(qǐng)求網(wǎng)絡(luò)。下面就記錄以下通過GCD和NSOperationQueue來控制并發(fā)。

二、代碼部分(GCD)

dispatch_semaphore ?信號(hào)量

信號(hào)量是一個(gè)整型值并且具有初始計(jì)數(shù)值,信號(hào)量通常支持兩個(gè)操作:通知和等待。當(dāng)信號(hào)被通知的時(shí)候計(jì)數(shù)值會(huì)增加,當(dāng)信號(hào)量在線程上等待的時(shí)候,必要的情況下線程會(huì)被阻塞掉,直至信號(hào)被通知時(shí)計(jì)數(shù)值大于0,然后線程會(huì)減少這個(gè)計(jì)數(shù)繼續(xù)工作。

GCD中又3個(gè)信號(hào)量有關(guān)的操作:

dispatch_semaphore_create    信號(hào)量創(chuàng)建

dispatch_semaphore_signal    發(fā)送通知

dispatch_semaphore_wait     信號(hào)量等待

GCD

#importint main(int argc, const char * argv[]) {

@autoreleasepool {

// 創(chuàng)建信號(hào)量

__block dispatch_semaphore_t sem = dispatch_semaphore_create(0);

// 創(chuàng)建隊(duì)列

dispatch_queue_t queue = dispatch_queue_create("testBlock", NULL);

dispatch_async(queue, ^{

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

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

}

// 發(fā)送通知

dispatch_semaphore_signal(sem);

});

// 信號(hào)量等待

dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);

for (int j = 0; j<20; j++) {

NSLog(@"j的值是:%d",j);

}

}

return 0;

}

打印結(jié)果為

2015-07-28 16:17:04.195多線程[16370:1833932] i的值是:0

2015-07-28 16:17:04.197多線程[16370:1833932] i的值是:1

2015-07-28 16:17:04.197多線程[16370:1833932] i的值是:2

2015-07-28 16:17:04.197多線程[16370:1833932] i的值是:3

2015-07-28 16:17:04.197多線程[16370:1833932] i的值是:4

2015-07-28 16:17:04.198多線程[16370:1833932] i的值是:5

2015-07-28 16:17:04.198多線程[16370:1833932] i的值是:6

2015-07-28 16:17:04.198多線程[16370:1833932] i的值是:7

2015-07-28 16:17:04.198多線程[16370:1833932] i的值是:8

2015-07-28 16:17:04.198多線程[16370:1833932] i的值是:9

2015-07-28 16:17:04.198多線程[16370:1833932] j的值是:0

2015-07-28 16:17:04.199多線程[16370:1833932] j的值是:1

2015-07-28 16:17:04.199多線程[16370:1833932] j的值是:2

2015-07-28 16:17:04.199多線程[16370:1833932] j的值是:3

2015-07-28 16:17:04.199多線程[16370:1833932] j的值是:4

2015-07-28 16:17:04.199多線程[16370:1833932] j的值是:5

2015-07-28 16:17:04.199多線程[16370:1833932] j的值是:6

2015-07-28 16:17:04.199多線程[16370:1833932] j的值是:7

2015-07-28 16:17:04.221多線程[16370:1833932] j的值是:8

2015-07-28 16:17:04.221多線程[16370:1833932] j的值是:9

2015-07-28 16:17:04.222多線程[16370:1833932] j的值是:10

2015-07-28 16:17:04.222多線程[16370:1833932] j的值是:11

2015-07-28 16:17:04.222多線程[16370:1833932] j的值是:12

2015-07-28 16:17:04.222多線程[16370:1833932] j的值是:13

2015-07-28 16:17:04.222多線程[16370:1833932] j的值是:14

2015-07-28 16:17:04.222多線程[16370:1833932] j的值是:15

2015-07-28 16:17:04.222多線程[16370:1833932] j的值是:16

2015-07-28 16:17:04.223多線程[16370:1833932] j的值是:17

2015-07-28 16:17:04.223多線程[16370:1833932] j的值是:18

2015-07-28 16:17:04.223多線程[16370:1833932] j的值是:19

我們看到先打印完i值后在打印j值 這就完成了并發(fā)請(qǐng)求

NSOperationQueue

- (void)viewDidLoad {

[super viewDidLoad];

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

// 創(chuàng)建一個(gè)隊(duì)列

NSOperationQueue *queue = [[NSOperationQueue alloc]init];

// 設(shè)置最大線程數(shù)

queue.maxConcurrentOperationCount = 5;

// 創(chuàng)建一個(gè)A操作

NSBlockOperation *operationA = [NSBlockOperation blockOperationWithBlock:^{

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

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

}

}];

// 創(chuàng)建一個(gè)B操作

NSBlockOperation *operationB = [NSBlockOperation blockOperationWithBlock:^{

for (int j = 0; j<20; j++) {

NSLog(@"j的值是:%d",j);

}

}];

// 分別加入到隊(duì)列中

[queue addOperation:operationA];

[queue addOperation:operationB];

}

打印結(jié)果

2015-07-28 17:51:09.508 111[16598:1880752] j的值是:0

2015-07-28 17:51:09.508 111[16598:1880750] i的值是:0

2015-07-28 17:51:09.509 111[16598:1880752] j的值是:1

2015-07-28 17:51:09.509 111[16598:1880750] i的值是:1

2015-07-28 17:51:09.509 111[16598:1880752] j的值是:2

2015-07-28 17:51:09.509 111[16598:1880750] i的值是:2

2015-07-28 17:51:09.509 111[16598:1880752] j的值是:3

2015-07-28 17:51:09.509 111[16598:1880750] i的值是:3

2015-07-28 17:51:09.509 111[16598:1880752] j的值是:4

2015-07-28 17:51:09.509 111[16598:1880750] i的值是:4

2015-07-28 17:51:09.509 111[16598:1880752] j的值是:5

2015-07-28 17:51:09.509 111[16598:1880750] i的值是:5

2015-07-28 17:51:09.509 111[16598:1880752] j的值是:6

2015-07-28 17:51:09.509 111[16598:1880750] i的值是:6

2015-07-28 17:51:09.509 111[16598:1880752] j的值是:7

2015-07-28 17:51:09.509 111[16598:1880750] i的值是:7

2015-07-28 17:51:09.509 111[16598:1880752] j的值是:8

2015-07-28 17:51:09.509 111[16598:1880750] i的值是:8

2015-07-28 17:51:09.510 111[16598:1880752] j的值是:9

2015-07-28 17:51:09.510 111[16598:1880750] i的值是:9

我們看到打印順序是交替進(jìn)行的。 那么如何進(jìn)行順序操作呢。只需一行代碼。

- (void)viewDidLoad {

[super viewDidLoad];

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

// 創(chuàng)建一個(gè)隊(duì)列

NSOperationQueue *queue = [[NSOperationQueue alloc]init];

// 設(shè)置最大線程數(shù)

queue.maxConcurrentOperationCount = 5;

// 創(chuàng)建一個(gè)A操作

NSBlockOperation *operationA = [NSBlockOperation blockOperationWithBlock:^{

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

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

}

}];

// 創(chuàng)建一個(gè)B操作

NSBlockOperation *operationB = [NSBlockOperation blockOperationWithBlock:^{

for (int j = 0; j<20; j++) {

NSLog(@"j的值是:%d",j);

}

}];

// 添加依賴 B要在A打印完在進(jìn)行打印 所以是B依賴于A 那么只需要添加如下代碼即可完成

[operationB addDependency:operationA];

// 分別加入到隊(duì)列中

[queue addOperation:operationA];

[queue addOperation:operationB];

}


打印結(jié)果

2015-07-28 17:54:02.606 111[16625:1882738] i的值是:0

2015-07-28 17:54:02.609 111[16625:1882738] i的值是:1

2015-07-28 17:54:02.609 111[16625:1882738] i的值是:2

2015-07-28 17:54:02.609 111[16625:1882738] i的值是:3

2015-07-28 17:54:02.609 111[16625:1882738] i的值是:4

2015-07-28 17:54:02.609 111[16625:1882738] i的值是:5

2015-07-28 17:54:02.609 111[16625:1882738] i的值是:6

2015-07-28 17:54:02.609 111[16625:1882738] i的值是:7

2015-07-28 17:54:02.610 111[16625:1882738] i的值是:8

2015-07-28 17:54:02.610 111[16625:1882738] i的值是:9

2015-07-28 17:54:02.610 111[16625:1882738] j的值是:0

2015-07-28 17:54:02.610 111[16625:1882738] j的值是:1

2015-07-28 17:54:02.610 111[16625:1882738] j的值是:2

2015-07-28 17:54:02.610 111[16625:1882738] j的值是:3

2015-07-28 17:54:02.610 111[16625:1882738] j的值是:4

2015-07-28 17:54:02.611 111[16625:1882738] j的值是:5

2015-07-28 17:54:02.611 111[16625:1882738] j的值是:6

2015-07-28 17:54:02.611 111[16625:1882738] j的值是:7

2015-07-28 17:54:02.611 111[16625:1882738] j的值是:8

2015-07-28 17:54:02.611 111[16625:1882738] j的值是:9

順序操作請(qǐng)求完成。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容