iOS GCD 基礎(chǔ)

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末赫蛇,一起剝皮案震驚了整個(gè)濱河市绵患,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌悟耘,老刑警劉巖落蝙,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異暂幼,居然都是意外死亡筏勒,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門旺嬉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來管行,“玉大人,你說我怎么就攤上這事邪媳〔⊥” “怎么了?”我有些...
    開封第一講書人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵悲酷,是天一觀的道長。 經(jīng)常有香客問我亲善,道長设易,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任蛹头,我火速辦了婚禮顿肺,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘渣蜗。我一直安慰自己屠尊,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開白布耕拷。 她就那樣靜靜地躺著讼昆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪骚烧。 梳的紋絲不亂的頭發(fā)上浸赫,一...
    開封第一講書人閱讀 49,079評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音赃绊,去河邊找鬼既峡。 笑死,一個(gè)胖子當(dāng)著我的面吹牛碧查,可吹牛的內(nèi)容都是我干的运敢。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼传惠!你這毒婦竟也來了迄沫?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤涉枫,失蹤者是張志新(化名)和其女友劉穎邢滑,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體愿汰,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡困后,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了衬廷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片摇予。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖吗跋,靈堂內(nèi)的尸體忽然破棺而出侧戴,到底是詐尸還是另有隱情,我是刑警寧澤跌宛,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布酗宋,位于F島的核電站,受9級(jí)特大地震影響疆拘,放射性物質(zhì)發(fā)生泄漏蜕猫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一哎迄、第九天 我趴在偏房一處隱蔽的房頂上張望回右。 院中可真熱鬧,春花似錦漱挚、人聲如沸翔烁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蹬屹。三九已至,卻和暖如春颊糜,著一層夾襖步出監(jiān)牢的瞬間哩治,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來泰國打工衬鱼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留业筏,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓鸟赫,卻偏偏與公主長得像蒜胖,于是被迫代替她去往敵國和親消别。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

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