在iOS中每個(gè)進(jìn)程啟動(dòng)后都會(huì)建立一個(gè)主線(xiàn)程(UI線(xiàn)程),這個(gè)線(xiàn)程是其他線(xiàn)程的父線(xiàn)程。由于在iOS中除了主線(xiàn)程,其他子線(xiàn)程是獨(dú)立于Cocoa Touch的,所以只有主線(xiàn)程可以更新UI界面(新版iOS中,使用其他線(xiàn)程更新UI可能也能成功,但是不推薦)。iOS中多線(xiàn)程使用并不復(fù)雜,關(guān)鍵是如何控制好各個(gè)線(xiàn)程的執(zhí)行順序、處理好資源競(jìng)爭(zhēng)問(wèn)題。常用的多線(xiàn)程開(kāi)發(fā)有三種方式:
1.NSThread
2.NSOperation
3.GCD
今天我們來(lái)談一談GCD,這在以后的開(kāi)發(fā)中最常用的。
我的IOS 交流群626433463
一、GCD基本概念
GCD 全稱(chēng)Grand Central Dispatch(大中樞隊(duì)列調(diào)度),是一套低層API,提供了?種新的方法來(lái)進(jìn)?并發(fā)程序編寫(xiě)。從基本功能上講,GCD有點(diǎn)像NSOperationQueue,他們都允許程序?qū)⑷蝿?wù)切分為多個(gè)單一任務(wù),然后提交??作隊(duì)列來(lái)并發(fā)的或者串?的執(zhí)行。GCD是C實(shí)現(xiàn),?NSOpertionQueue更底層更高效,并且它不是Cocoa框架的一部分 并發(fā)任務(wù)會(huì)像NSOperationQueue那樣基于系統(tǒng)負(fù)載來(lái)合適地并發(fā)進(jìn)?,而串?行隊(duì)列同一時(shí)間只執(zhí)行單一任務(wù),GCD的API很大程度上基于block。
GCD并發(fā)編程的主要好處歸納
GCD可用于多核的并行運(yùn)算
GCD會(huì)自動(dòng)利用更多的CPU內(nèi)核(比如雙核、四核)
GCD會(huì)自動(dòng)管理線(xiàn)程的生命周期(創(chuàng)建線(xiàn)程、調(diào)度任務(wù)、銷(xiāo)毀線(xiàn)程)
程序員只需要告訴GCD想要執(zhí)行什么任務(wù),不需要編寫(xiě)任何線(xiàn)程管理代碼
二、GCD如何實(shí)現(xiàn)
GCD主要由隊(duì)列和任務(wù)兩部分來(lái)實(shí)現(xiàn),蘋(píng)果官方對(duì)GCD是這樣說(shuō)明的:開(kāi)發(fā)者要做的只是定義想執(zhí)行的任務(wù)并追加到適當(dāng)?shù)腄ispatch Queue中。Dispatch Queue是執(zhí)行處理的等待隊(duì)列,我們可以通過(guò)dispatch_async等API,在block語(yǔ)法中記述想要執(zhí)行的處理并將其追加到Dispatch Queue中,Dispatch Queue是按照追加的順序進(jìn)行處理(先進(jìn)先出FIFO)。
說(shuō)到GCD,必須強(qiáng)調(diào)隊(duì)列和任務(wù)兩個(gè)詞,很多人容易搞混(當(dāng)然,本人一開(kāi)始接觸ios也是一樣懵逼),隊(duì)列其實(shí)就跟物理課上的串聯(lián),并聯(lián)電路差不多吧,任務(wù)就是同異步之分,同步不開(kāi)啟線(xiàn)程,異步開(kāi)啟新線(xiàn)程。這里就簡(jiǎn)單明了的說(shuō)下吧:
隊(duì)列:
串行隊(duì)列:在隊(duì)列中多個(gè)線(xiàn)程中有序進(jìn)行;
并行隊(duì)列:在隊(duì)列中多個(gè)線(xiàn)程同時(shí)進(jìn)行,沒(méi)有順序;
任務(wù):
同步: sync ,它會(huì)阻塞當(dāng)前線(xiàn)程,等待隊(duì)列中的任務(wù)執(zhí)行完畢,然后當(dāng)前線(xiàn)程才會(huì)繼續(xù);
異步:async,不會(huì)阻塞線(xiàn)程,會(huì)直接往下執(zhí)行;
代碼:
1.主線(xiàn)程隊(duì)列:
主線(xiàn)程異步隊(duì)列中,也是順序執(zhí)行的,主線(xiàn)程中有任務(wù),必須等主線(xiàn)程中的任務(wù)執(zhí)行完畢才執(zhí)行主隊(duì)列,如果主線(xiàn)程中使用同步隊(duì)列將會(huì)導(dǎo)致線(xiàn)程鎖死,這點(diǎn)要注意,鎖死的原因是循環(huán)等待,主隊(duì)列的東西要等主線(xiàn)程執(zhí)行完,而因?yàn)橥綀?zhí)行不能開(kāi)線(xiàn)程,所以下面的任務(wù)要等上面的任務(wù)執(zhí)行完,所以鎖死。
//主異步:在主線(xiàn)程中順序執(zhí)行
dispatch_queue_t main = dispatch_get_main_queue();
for (int i = 0; i < 10; i++) {
dispatch_async(main, ^{
NSLog(@"主隊(duì)列,異步%@",[NSThread currentThread]);
});
}
}
//主同步:會(huì)造成線(xiàn)程鎖死
dispatch_queue_t main = dispatch_get_main_queue();
for (int i = 0; i < 0; i++) {
dispatch_sync(main, ^{
NSLog(@"你這是要鎖死我%@",[NSThread currentThread]);
});
}
2.串行隊(duì)列:
//串行同步:不開(kāi)線(xiàn)程,在當(dāng)前線(xiàn)程中有序的進(jìn)行
dispatch_queue_t queue = dispatch_queue_create("serial", DISPATCH_QUEUE_SERIAL);
for (int i = 0; i < 10; i++) {
dispatch_sync(cxTongB, ^{
NSLog(@"串行隊(duì)列,同步%@",[NSThread currentThread]);
});
}
//串行異步:開(kāi)啟一條線(xiàn)程,然后有序的執(zhí)行
dispatch_queue_t queue = dispatch_queue_create("YIBU", DISPATCH_QUEUE_SERIAL);
for (int i = 0; i < 10; i++) {
dispatch_async(queue, ^{
NSLog(@"串行隊(duì)列,異步%@",[NSThread currentThread]);
});
}
3.并行隊(duì)列
//并行同步:不開(kāi)啟線(xiàn)程,在當(dāng)前線(xiàn)程有序進(jìn)行
dispatch_queue_t bxtongbu = dispatch_queue_create("bxtongbu", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i < 10; i++) {
//同步執(zhí)行
dispatch_sync(bxtongbu, ^{
NSLog(@"并行隊(duì)列,同步%@",[NSThread currentThread]);
});
}
//并行異步:開(kāi)啟多條線(xiàn)程,并發(fā)執(zhí)行
dispatch_queue_t queue = dispatch_queue_create("bxYibu", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i < 10 ; i++) {
dispatch_sync(queue, ^{
NSLog(@"并行隊(duì)列,異步%@",[NSThread currentThread]);
});
}
總結(jié):

1. 開(kāi)不開(kāi)線(xiàn)程,取決于執(zhí)行任務(wù)的函數(shù),同步不開(kāi),異步開(kāi)。
2. 開(kāi)幾條線(xiàn)程,取決于隊(duì)列,串行開(kāi)一條,并發(fā)開(kāi)多條(異步)
3. 主隊(duì)列:專(zhuān)門(mén)用來(lái)在主線(xiàn)程上調(diào)度任務(wù)的"隊(duì)列",主隊(duì)列不能在其他線(xiàn)程中調(diào)度任務(wù)
4. 如果主線(xiàn)程上當(dāng)前正在有執(zhí)行的任務(wù),主隊(duì)列暫時(shí)不會(huì)調(diào)度任務(wù)的執(zhí)行!主隊(duì)列同步任務(wù),會(huì)造成死鎖。原因是循環(huán)等待
5. 同步任務(wù)可以隊(duì)列調(diào)度多個(gè)異步任務(wù)前,指定一個(gè)同步任務(wù),讓所有的異步任務(wù),等待同步任務(wù)執(zhí)行完成,這是依賴(lài)關(guān)系。
6. 全局隊(duì)列:并發(fā),能夠調(diào)度多個(gè)線(xiàn)程,執(zhí)行效率高,但是相對(duì)費(fèi)電。 串行隊(duì)列效率較低,省電省流量,或者是任務(wù)之間需要依賴(lài)也可以使用串行隊(duì)列。
7. 也可以通過(guò)判斷當(dāng)前用戶(hù)的網(wǎng)絡(luò)環(huán)境來(lái)決定開(kāi)的線(xiàn)程數(shù)。