iOS GCD 基礎(chǔ)
介紹
GCD涯雅,英文全稱是Grand Central Dispatch柱搜,是基于C語言編寫的一套多線程開發(fā)機(jī)制辩诞,因此實(shí)用時(shí)會(huì)以函數(shù)形式出現(xiàn)课幕,且大部分函數(shù)以dispatch開頭,雖然是C語言的但相對(duì)于蘋果其他多線程實(shí)現(xiàn)方式露该,抽象層次更高睬棚,實(shí)用起來也更加方便。
基礎(chǔ)概念
GCD有兩個(gè)核心:任務(wù)和隊(duì)列。
1. 任務(wù)
任務(wù)是一個(gè)比較抽象的概念抑党,可以簡(jiǎn)單的認(rèn)為是一個(gè)操作包警、一個(gè)函數(shù)、一個(gè)方法等等底靠,在實(shí)際的開發(fā)中大多是以block的形式害晦,實(shí)用起來也更加靈活。
2. 隊(duì)列 queue
有兩種隊(duì)列:串行隊(duì)列和并行隊(duì)列苛骨。串行隊(duì)列:同步執(zhí)行篱瞎,在當(dāng)前線程執(zhí)行;并行隊(duì)列:可由多個(gè)線程異步執(zhí)行痒芝,但任務(wù)的取出還是FIFO的。
隊(duì)列創(chuàng)建牵素,根據(jù)函數(shù)第二個(gè)參數(shù)來創(chuàng)建串行或并行隊(duì)列严衬。
//創(chuàng)建并行隊(duì)列
//參數(shù)1 隊(duì)列名稱
//參數(shù)2 隊(duì)列類型 :
//DISPATCH_QUEUE_SERIAL/NULL串行隊(duì)列 //DISPATCH_QUEUE_CONCURRENT并行隊(duì)列
dispatch_queue_t queue = dispatch_queue_create("標(biāo)識(shí)符", DISPATCH_QUEUE_CONCURRENT);
- 另外系統(tǒng)提供了兩種隊(duì)列:全局隊(duì)列和主隊(duì)列。
全局隊(duì)列屬于并行隊(duì)列笆呆,只不過已由系統(tǒng)創(chuàng)建的沒有名字请琳,且在全局可見。
//獲取全局隊(duì)列
//第一個(gè)參數(shù):線程優(yōu)先級(jí)赠幕,設(shè)為默認(rèn)即可俄精,個(gè)人習(xí)慣寫0,等同于默認(rèn)
//第二個(gè)參數(shù):標(biāo)記參數(shù)榕堰,目前沒有用竖慧,一般傳入0
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
主隊(duì)列屬于串行隊(duì)列,也由系統(tǒng)創(chuàng)建逆屡,只不過在主線程圾旨。
//獲取主隊(duì)列
dispatch_queue_t queue = dispatch_get_main_queue();
- queue 屬于一個(gè)對(duì)象,也是占用內(nèi)存的魏蔗,也會(huì)實(shí)用引用計(jì)數(shù)砍的,當(dāng)向queue添加一個(gè)任務(wù)時(shí)就會(huì)將這個(gè)queue引用計(jì)數(shù)加1,直到所有任務(wù)都完成內(nèi)存才會(huì)釋放莺治。我們?cè)诼暶鱭ueue屬性時(shí)要用strong.
執(zhí)行方式
- 同步執(zhí)行:不會(huì)開啟新的線程廓鞠,在當(dāng)前線程執(zhí)行。
- 異步執(zhí)行:GCD管理的線程池有空閑就會(huì)從隊(duì)列中取出任務(wù)執(zhí)行谣旁,會(huì)開啟線程床佳。
//同步執(zhí)行
//第一個(gè)參數(shù):執(zhí)行任務(wù)的隊(duì)列:串行、并行蔓挖、全局夕土、主隊(duì)列
//第二個(gè)參數(shù):block任務(wù)
dispatch_sync(dispatch_queue_t queue, dispatch_block_t
block);
//異步執(zhí)行
dispatch_async(dispatch_queue_t queue, dispatch_block_t
block);
幾種類型
1. 異步執(zhí)行、并行隊(duì)列
//創(chuàng)建并行隊(duì)列
dispatch_queue_t queue = dispatch_queue_create("標(biāo)識(shí)符",
DISPATCH_QUEUE_CONCURRENT);
NSLog(@"start =====");
//異步執(zhí)行三個(gè)任務(wù)
dispatch_async(queue, ^{
NSLog(@"task 1 : %@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"task 2: %@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"task 3: %@",[NSThread currentThread]);
});
NSLog(@"end =====");
結(jié)果:
解釋:
異步執(zhí)行意味著可以開啟新的線程,任務(wù)可以先繞過不執(zhí)行怨绣,回頭再來執(zhí)行角溃。
并行隊(duì)列意味著任務(wù)之間不需要排隊(duì),且具有同時(shí)被執(zhí)行的權(quán)利篮撑。
兩者組合后的結(jié)果是開啟了三個(gè)新線程减细,在執(zhí)行時(shí)先打印了start和end,再回頭執(zhí)行這三個(gè)任務(wù)赢笨。這三個(gè)任務(wù)同時(shí)執(zhí)行未蝌,沒有先后。
2. 異步執(zhí)行茧妒、串行隊(duì)列
dispatch_queue_t queue = dispatch_queue_create("id",
DISPATCH_QUEUE_SERIAL);
NSLog(@"start =====");
dispatch_async(queue, ^{
NSLog(@"task 1 : %@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"task 2: %@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"task 3: %@",[NSThread currentThread]);
});
NSLog(@"end =====");
結(jié)果:
解釋:
異步執(zhí)行意味著可以開啟新的線程萧吠,任務(wù)可以先繞過不執(zhí)行,回頭再來執(zhí)行
串行隊(duì)列意味著任務(wù)必須按添加進(jìn)隊(duì)列的順序執(zhí)行
兩者組合后的結(jié)果是開啟了一個(gè)新的子線程桐筏,在執(zhí)行時(shí)纸型,先打印了start和end,再回頭執(zhí)行這三個(gè)任務(wù)
3. 同步執(zhí)行梅忌、并行隊(duì)列
dispatch_queue_t queue = dispatch_queue_create("id",
DISPATCH_QUEUE_CONCURRENT);
NSLog(@"start =====");
dispatch_sync(queue, ^{
NSLog(@"task 1 : %@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"task 2: %@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"task 3: %@",[NSThread currentThread]);
});
NSLog(@"end =====");
結(jié)果:
解釋:
同步執(zhí)行意味著不能開啟新的線程狰腌,創(chuàng)建任務(wù)后必須執(zhí)行完才能往下走
并行隊(duì)列意味著任務(wù)必須按添加進(jìn)隊(duì)列的順序執(zhí)行
兩者組合后結(jié)果是所有任務(wù)都只能在主線程執(zhí)行,在執(zhí)行時(shí)牧氮,必須按照代碼的書寫順序一行一行執(zhí)行完才能繼續(xù)琼腔。
注意:這里即便是并行隊(duì)列,任務(wù)可以同時(shí)執(zhí)行踱葛,但是由于只存在一個(gè)主線程丹莲,所以沒法把任務(wù)分發(fā)到不同的線程去處理,其結(jié)果是只能在主線程里按順序執(zhí)行
4. 同步執(zhí)行剖毯、串行隊(duì)列
dispatch_queue_t queue = dispatch_queue_create("id",
DISPATCH_QUEUE_SERIAL);
NSLog(@"start =====");
dispatch_sync(queue, ^{
NSLog(@"task 1 : %@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"task 2: %@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"task 3: %@",[NSThread currentThread]);
});
NSLog(@"end =====");
結(jié)果:
解釋:
這里的執(zhí)行原理和步驟跟“同步執(zhí)行圾笨、并行隊(duì)列”是一樣的,只要是同步執(zhí)行就沒發(fā)開啟新的線程逊谋,所以多個(gè)任務(wù)之間也是只能按順序執(zhí)行
5. 異步執(zhí)行擂达、主隊(duì)列
dispatch_queue_t queue = dispatch_get_main_queue();
NSLog(@"start =====");
dispatch_async(queue, ^{
NSLog(@"task 1 : %@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"task 2: %@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"task 3: %@",[NSThread currentThread]);
});
NSLog(@"end =====");
結(jié)果:
解釋:
異步執(zhí)行意味著可以開啟新的線程,任務(wù)可以先繞過不執(zhí)行胶滋,回頭再來執(zhí)行
主隊(duì)列跟串行隊(duì)列的區(qū)別板鬓,隊(duì)列中的任務(wù)一樣要按順序執(zhí)行,主隊(duì)列中的任務(wù)必須在主線程中執(zhí)行究恤,不允許在子線程中執(zhí)行
兩者組合的結(jié)果是所有任務(wù)都可以先跳過俭令,之后再來按順序執(zhí)行
6. 同步執(zhí)行、主隊(duì)列(死鎖)
dispatch_queue_t queue = dispatch_get_main_queue();
NSLog(@"start =====");
dispatch_sync(queue, ^{
NSLog(@"task 1 : %@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"task 2: %@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"task 3: %@",[NSThread currentThread]);
});
NSLog(@"end =====");
結(jié)果:
解釋:
主隊(duì)列中的任務(wù)必須按順序執(zhí)行部宿,任務(wù)1要等主線程有空的時(shí)候即主隊(duì)列中的所有任務(wù)執(zhí)行完后才能執(zhí)行抄腔。主線程要執(zhí)行完但因"end"的任務(wù)后才有空瓢湃,任務(wù)1和打印"end"兩個(gè)任務(wù)互相等待,造成死鎖
參考文章:
文章1:http://www.reibang.com/p/33151a5bac28
文章2:https://www.52jbj.com/rjbc/539710.html