iOS開發(fā)之淺談GCD

蘋果為了減少我們開發(fā)者對(duì)多線程的開發(fā)難度娇昙,提供了兩種比較牛的并發(fā)編程技術(shù)。GCD和NSOperation蹲盘,下面我們來初步的認(rèn)識(shí)一下GCD及簡單的使用。

一苍凛、認(rèn)識(shí)GCD

1.什么是GCD?

  • 全稱為Grand Central Dispatch悠栓,可譯為“牛逼的中樞調(diào)度器”
  • 純C語言惭适,提供了非常強(qiáng)大的函數(shù)

2.GCD的優(yōu)勢

  • GCD是蘋果為了多核的并行運(yùn)算提出的解決方案
  • GCD會(huì)自動(dòng)利用更多的CPU內(nèi)核(比如雙核、四核凄杯、八核)
  • GCD會(huì)自動(dòng)管理線程的生命周期(創(chuàng)建線程、調(diào)度任務(wù)、銷毀線程)
  • 程序員只需要告訴GCD想要執(zhí)行什么任務(wù),不需要編寫任何線程管理代碼

二窑多、GCD的基本概念(隊(duì)列和任務(wù))

1.GCD中有兩個(gè)核心概念

  • 隊(duì)列:用來存放任務(wù)(分為:串行隊(duì)列&并發(fā)隊(duì)列&全局隊(duì)列)
  • 任務(wù):執(zhí)行什么操作(分為:同步執(zhí)行&異步執(zhí)行)

2.GCD的使用步驟就兩個(gè)

  • 定制任務(wù)(做你想做的事,任你YY)
  • 將任務(wù)添加到隊(duì)列中(GCD會(huì)自動(dòng)將任務(wù)取出千康,放到對(duì)應(yīng)的線程執(zhí)行值桩。取出任務(wù)的原則為FIFO:先進(jìn)先出,后進(jìn)后出)

二咳秉、簡單的使用GCD

1.GCD的創(chuàng)建方式

1.串行隊(duì)列的創(chuàng)建

//1.隊(duì)列 - 串行
/**
 1.隊(duì)列名稱:
 2.隊(duì)列的屬性: DISPATCH_QUEUE_SERIAL 標(biāo)示串行!
 */
dispatch_queue_t d = dispatch_queue_create("chuanxing", NULL);

串行隊(duì)列里的任務(wù)執(zhí)行方式:一個(gè)一個(gè)執(zhí)行揭芍,上一個(gè)任務(wù)執(zhí)行完了才能進(jìn)行下一個(gè)任務(wù)

2.并發(fā)隊(duì)列的創(chuàng)建

//2.隊(duì)列 - 并發(fā)
/**
 1.隊(duì)列名稱:
 2.隊(duì)列的屬性: DISPATCH_QUEUE_CONCURRENT 標(biāo)示并發(fā)!
 */
dispatch_queue_t d = dispatch_queue_create("bingfa", DISPATCH_QUEUE_CONCURRENT);

并行隊(duì)列里的任務(wù)執(zhí)行方式:不需要等待上一個(gè)任務(wù)執(zhí)行完靶累,就可以取出下一個(gè)任務(wù)到對(duì)應(yīng)的線程去執(zhí)行

3.同步執(zhí)行任務(wù)

//3.任務(wù) - 同步
/**
 1.隊(duì)列:dispatch_queue_t
 2.任務(wù):把任務(wù)放到這個(gè)隊(duì)列里去執(zhí)行
 */
dispatch_sync(d, ^{
        NSLog(@"%@",[NSThread currentThread]);
    });

同步執(zhí)行方式:上個(gè)任務(wù)沒執(zhí)行完庇忌,就不會(huì)執(zhí)行下個(gè)任務(wù)疏橄,同步執(zhí)行不會(huì)開啟線程

4.異步執(zhí)行任務(wù)

//3.任務(wù) - 異步
/**
 1.隊(duì)列:dispatch_queue_t
 2.任務(wù):把任務(wù)放到這個(gè)隊(duì)列里去執(zhí)行
 */
dispatch_async(d, ^{
        NSLog(@"%@",[NSThread currentThread]);
    });

異步執(zhí)行方式:上個(gè)任務(wù)沒執(zhí)行完,也會(huì)異步執(zhí)行下個(gè)任務(wù),異步執(zhí)行具備開啟線程的能力(并不是一定會(huì)開啟線程蛔翅,異步通常就是多線程的代名詞!8峭取!)

注:GCD的線程池,給不給你的任務(wù)開啟子線程,看你的任務(wù)執(zhí)行的是同步還是異步蛛砰。
同步任務(wù):不會(huì)開啟子線程去執(zhí)行任務(wù)琅翻,只會(huì)讓同步任務(wù)在當(dāng)前的線程一個(gè)一個(gè)去執(zhí)行聂抢。不管任務(wù)所在的隊(duì)列是串行的還是并發(fā)的闸拿。任務(wù)只會(huì)在當(dāng)前的線程執(zhí)行,GCD不會(huì)再為其開啟另外的線程去執(zhí)行任務(wù)但骨。
異步任務(wù):具備開啟線程的能力吼野,但不一定會(huì)開啟闷哆,要看任務(wù)所在的隊(duì)列是串行的還是并發(fā)的嘀倒。如果是串行的,任務(wù)是一個(gè)一個(gè)執(zhí)行的,即使具備開啟線程的能力,但是沒有多余的任務(wù)可以去讓GCD開啟線程贝攒。如果是并發(fā),不需要等待上一個(gè)任務(wù)執(zhí)行完咽扇,下一個(gè)任務(wù)就可以取出去執(zhí)行了,這時(shí)又具備開啟線程能力树埠,所以GCD會(huì)為這個(gè)異步任務(wù)開啟線程糠馆。

2.GCD的基本使用

1.串行隊(duì)列,同步任務(wù)

//MARK:串行隊(duì)列,同步任務(wù)
/**
*   不會(huì)開啟線程,會(huì)順序執(zhí)行
*/
-(void)GCDDemo1{
    //1.隊(duì)列 - 串行
    /**
     1.隊(duì)列名稱:
     2.隊(duì)列的屬性: DISPATCH_QUEUE_SERIAL 標(biāo)示串行!
     */
    dispatch_queue_t d = dispatch_queue_create("chuanxing", NULL);
    
    //2.同步執(zhí)行任務(wù)
    for (int i = 0; i < 10; i++) {
        dispatch_sync(d, ^{
            NSLog(@"%@ %d",[NSThread currentThread],i);
        });
    }   
}

運(yùn)行結(jié)果:沒有開啟線程怎憋,按順序執(zhí)行


image.png

2.串行隊(duì)列又碌,異步任務(wù)

//MARK:串行隊(duì)列,異步任務(wù)
/**
*   會(huì)開啟子線程,按順序執(zhí)行
*/
-(void)GCDDemo1{
    //1.隊(duì)列 - 串行
    /**
     1.隊(duì)列名稱:
     2.隊(duì)列的屬性: DISPATCH_QUEUE_SERIAL 標(biāo)示串行!
     */
    dispatch_queue_t d = dispatch_queue_create("chuanxing", NULL);
    
    //2.異步執(zhí)行任務(wù)
    for (int i = 0; i < 10; i++) {
        dispatch_async(d, ^{
            NSLog(@"%@ %d",[NSThread currentThread],i);
        });
    }   
}

運(yùn)行結(jié)果:開啟了子線程,按順序執(zhí)行(只會(huì)開啟一條子線程)


image.png

3.并發(fā)隊(duì)列绊袋,異步任務(wù)

//MARK:并發(fā)隊(duì)列毕匀,異步任務(wù)
/**
*   會(huì)開啟子線程,不按順序執(zhí)行
*/
-(void)GCDDemo1{
    //1.隊(duì)列 - 并發(fā)
    /**
     1.隊(duì)列名稱:
     2.隊(duì)列的屬性: DISPATCH_QUEUE_CONCURRENT 標(biāo)示并發(fā)!
     */
    dispatch_queue_t d = dispatch_queue_create("bingfa", DISPATCH_QUEUE_CONCURRENT);
    
    //2.異步執(zhí)行任務(wù)
    for (int i = 0; i < 10; i++) {
        dispatch_async(d, ^{
            NSLog(@"%@ %d",[NSThread currentThread],i);
        });
    }   
}

運(yùn)行結(jié)果:開啟了子線程,不按順序執(zhí)行(任務(wù)需要多少子線程就會(huì)開啟多少子線程)每一次的運(yùn)行結(jié)果都會(huì)不一樣


image.png

4.并發(fā)隊(duì)列愤炸,同步任務(wù)

//MARK:并發(fā)隊(duì)列期揪,同步任務(wù)
/**
*   不會(huì)開啟子線程,按順序執(zhí)行
*/
-(void)GCDDemo1{
    //1.隊(duì)列 - 并發(fā)
    /**
     1.隊(duì)列名稱:
     2.隊(duì)列的屬性: DISPATCH_QUEUE_CONCURRENT 標(biāo)示并發(fā)!
     */
    dispatch_queue_t d = dispatch_queue_create("bingfa", DISPATCH_QUEUE_CONCURRENT);
    
    //2.同步執(zhí)行任務(wù)
    for (int i = 0; i < 10; i++) {
        dispatch_sync(d, ^{
            NSLog(@"%@ %d",[NSThread currentThread],i);
        });
    }   
}

運(yùn)行結(jié)果:沒有開啟線程,按順序執(zhí)行


image.png

5.還有一個(gè)-->全局隊(duì)列

dispatch_queue_t d = dispatch_get_global_queue(0, 0);

全局隊(duì)列本質(zhì)上是一個(gè)并發(fā)隊(duì)列

    /* 參數(shù)
     1. 涉及到系統(tǒng)適配
     iOS 8   服務(wù)質(zhì)量
     QOS_CLASS_USER_INTERACTIVE    用戶交互(希望線程快速被執(zhí)行,不要用好使的操作)
     QOS_CLASS_USER_INITIATED      用戶需要的(同樣不要使用耗時(shí)操作)
     QOS_CLASS_DEFAULT             默認(rèn)的(給系統(tǒng)來重置隊(duì)列的)
     QOS_CLASS_UTILITY             使用工具(用來做耗時(shí)操作)
     QOS_CLASS_BACKGROUND          后臺(tái)
     QOS_CLASS_UNSPECIFIED         沒有指定優(yōu)先級(jí)
     iOS 7  調(diào)度的優(yōu)先級(jí)
     - DISPATCH_QUEUE_PRIORITY_HIGH 2               高優(yōu)先級(jí)
     - DISPATCH_QUEUE_PRIORITY_DEFAULT 0            默認(rèn)優(yōu)先級(jí)
     - DISPATCH_QUEUE_PRIORITY_LOW (-2)             低優(yōu)先級(jí)
     - DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN 后臺(tái)優(yōu)先級(jí)
     
     提示:尤其不要選擇BACKGROUND 優(yōu)先級(jí),服務(wù)質(zhì)量,線程執(zhí)行會(huì)慢到令人發(fā)指!!!
     
     
     2. 為未來使用的一個(gè)保留,現(xiàn)在始終給0.
     
     老項(xiàng)目中,一般還是沒有淘汰iOS 7  ,沒法使用服務(wù)質(zhì)量
     */

//MARK: - 利用GCD 來做下載圖片
    //異步執(zhí)行
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSURL * url = [NSURL URLWithString:@"http://img3.duitang.com/uploads/item/201604/27/20160427004300_QfKwt.jpeg"];
        NSData * data = [NSData dataWithContentsOfURL:url];
        UIImage * image = [UIImage imageWithData:data];


        //更新UI规个,回到主隊(duì)列dispatch_get_main_queue()凤薛,這叫線程間的通訊
        //這里不存在循環(huán)引用,這里的block不是屬性诞仓,不會(huì)被控制器拿到缤苫,所以不用管循環(huán)引用的問題
        //主隊(duì)列是串行隊(duì)列(而且不會(huì)管你異步任務(wù)還是同步任務(wù),絕對(duì)不會(huì)開啟子線程)墅拭,所以這里用同步執(zhí)行任務(wù)和異步執(zhí)行任務(wù)都一樣
        dispatch_async(dispatch_get_main_queue(), ^{
            self.imageView.image = image;
            [self.imageView sizeToFit];
        });
    });

提問
問題:GCD是C語言的框架活玲,在C語言中遇到了get、new谍婉、copy舒憾、create...等等這些字樣,都需要釋放內(nèi)存穗熬《朴兀可是上面的代碼都沒有release,為什么唤蔗?
搶地主:GCD在iOS開發(fā)中太常用了探遵,ARC情況下不需要release(在MRC下,只有并發(fā)隊(duì)列才需要被release妓柜,全局隊(duì)列是不需要的)

再問:在開發(fā)過程中如何選擇隊(duì)列箱季?
我搶:
     - 全局隊(duì)列,并發(fā)棍掐,能調(diào)度多個(gè)線程藏雏,執(zhí)行效率高。BUT作煌,耗電诉稍,發(fā)燙(王炸)r鸺巍!杯巨!
     - 串行隊(duì)列,一個(gè)一個(gè)執(zhí)行努酸,執(zhí)行效率低(快點(diǎn)啊服爷,我等的花兒都謝了)。BUT获诈,我省電叭栽础!L蛳选笼踩!
     - 可根據(jù)用戶上網(wǎng)的模式選擇:WIFI(全局隊(duì)列),流量(少開線程亡嫌,串行隊(duì)列)
小結(jié):
  • 開不開線程:取決于執(zhí)行任務(wù)的函數(shù)嚎于,同步不開,異步才能開
  • 開幾條線程:取決于隊(duì)列挟冠,串行開一條于购,并發(fā)開多條(異步)


    image.png

注:以上幾種GCD的基本使用,可以互相套用知染,自己試試看肋僧,你會(huì)發(fā)現(xiàn)新大陸的。(同一個(gè)隊(duì)列上面的任務(wù)控淡,不一定都是一樣的嫌吠,可以是同步任務(wù)混合異步任務(wù))

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市掺炭,隨后出現(xiàn)的幾起案子辫诅,更是在濱河造成了極大的恐慌,老刑警劉巖竹伸,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件泥栖,死亡現(xiàn)場離奇詭異,居然都是意外死亡勋篓,警方通過查閱死者的電腦和手機(jī)吧享,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來譬嚣,“玉大人钢颂,你說我怎么就攤上這事“菀” “怎么了殊鞭?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵遭垛,是天一觀的道長。 經(jīng)常有香客問我操灿,道長锯仪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任趾盐,我火速辦了婚禮庶喜,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘救鲤。我一直安慰自己久窟,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布本缠。 她就那樣靜靜地躺著斥扛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪丹锹。 梳的紋絲不亂的頭發(fā)上稀颁,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音卷仑,去河邊找鬼峻村。 笑死,一個(gè)胖子當(dāng)著我的面吹牛锡凝,可吹牛的內(nèi)容都是我干的粘昨。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼窜锯,長吁一口氣:“原來是場噩夢啊……” “哼张肾!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起锚扎,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤吞瞪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后驾孔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體芍秆,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年翠勉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了妖啥。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡对碌,死狀恐怖荆虱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤怀读,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布诉位,位于F島的核電站,受9級(jí)特大地震影響菜枷,放射性物質(zhì)發(fā)生泄漏苍糠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一犁跪、第九天 我趴在偏房一處隱蔽的房頂上張望椿息。 院中可真熱鬧,春花似錦坷衍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至孟抗,卻和暖如春迁杨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背凄硼。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留狐史,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓棺棵,卻偏偏與公主長得像烛恤,于是被迫代替她去往敵國和親糙申。 傳聞我的和親對(duì)象是個(gè)殘疾皇子柜裸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

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