二洒敏、GCD

1. GCD的基本使用

CGD是蘋果公司為多核的并行運(yùn)算提出的解決方案,會(huì)自動(dòng)利用更多的CPU內(nèi)核疙驾,自動(dòng)管理線程的生命周期(創(chuàng)建線程凶伙、調(diào)度任務(wù)、銷毀線程)它碎。So镊靴,我們只需告訴CGD勞資想執(zhí)行啥任務(wù)铣卡,不需要編寫任何線程管理的代碼。使用CGD來(lái)處理多線程問(wèn)題爽的不要不要的??

1.1 概念:

1.1.1 任務(wù)

任務(wù)就是執(zhí)行什么操作偏竟。任務(wù)分為同步任務(wù)異步任務(wù)煮落,同步任務(wù)在當(dāng)前線程中執(zhí)行,異步任務(wù)在另一線程中執(zhí)行踊谋。

// 同步方式執(zhí)行任務(wù)
// queue:隊(duì)列
// block:任務(wù)
dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);

// 異步方式執(zhí)行任務(wù)
dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
1.1.2 隊(duì)列

隊(duì)列就是存放任務(wù)的容器蝉仇。隊(duì)列分為串行隊(duì)列并行隊(duì)列,并發(fā)隊(duì)列可以讓多個(gè)任務(wù)并發(fā)(即同時(shí))執(zhí)行(自動(dòng)開(kāi)啟多個(gè)線程同時(shí)執(zhí)行任務(wù))殖蚕,so轿衔,并發(fā)任務(wù)只有在異步下才有效哦??;串行隊(duì)列中任務(wù)一個(gè)一個(gè)排隊(duì)執(zhí)行睦疫,跟我們排隊(duì)打飯類似哦害驹!

CGD的使用就下面兩步:

  1. 定制任務(wù)(要干什么)
  2. 將任務(wù)添加到隊(duì)列中。CGD會(huì)自動(dòng)將隊(duì)列中的任務(wù)取出放到對(duì)應(yīng)的線程中執(zhí)行蛤育,任務(wù)的取出遵循隊(duì)列的FIFO原則宛官。

下面給大家show一把這4種組合??:

1.2. 串行隊(duì)列 + 同步任務(wù)

   /**
     1. 創(chuàng)建一個(gè)串行隊(duì)列

     @param "lile" 隊(duì)列標(biāo)簽
     @param DISPATCH_QUEUE_SERIAL 隊(duì)列的屬性, serial:連續(xù)的瓦糕,看來(lái)學(xué)好英文對(duì)編程很重要哦底洗!
     @return 串行隊(duì)列
     */
    dispatch_queue_t queue = dispatch_queue_create("lile", DISPATCH_QUEUE_SERIAL);

    // 2. 同步執(zhí)行任務(wù)
    // 一般只要使用”同步“執(zhí)行,串行隊(duì)列對(duì)添加的同步任務(wù)咕娄,會(huì)立馬執(zhí)行
    dispatch_sync(queue, ^{
        NSLog(@"%@", [NSThread currentThread]);
    });

不開(kāi)新線程亥揖,在當(dāng)前線程(即主線程)順序執(zhí)行

1.3 串行隊(duì)列 + 異步執(zhí)行

    // 1. 串行隊(duì)列
    // 下面兩種寫法是一樣的
    dispatch_queue_t queue1 = dispatch_queue_create("lile", DISPATCH_QUEUE_SERIAL);
    dispatch_queue_t queue2 = dispatch_queue_create("lile", NULL);

    
    // 2. 異步執(zhí)行
    for (int i = 0; i < 10; i++) {
        dispatch_async(queue1, ^{
            NSLog(@"%@ %d", [NSThread currentThread], i);
        });
    }

只會(huì)開(kāi)一個(gè)線程(非主線程),而且所有任務(wù)都在這個(gè)新的線程里面執(zhí)行

1.4 并行隊(duì)列 + 同步執(zhí)行

    //  1. 并行隊(duì)列圣勒,concurrent:并發(fā)的费变,同時(shí)發(fā)生的
    dispatch_queue_t queue = dispatch_queue_create("lile", DISPATCH_QUEUE_CONCURRENT);
    
    // 2. 同步執(zhí)行任務(wù)
    for (int i = 0; i < 10; i++) {
        dispatch_sync(queue, ^{
            NSLog(@"%@ %d", [NSThread currentThread], i);
        });
    }

不開(kāi)新線程,順序一個(gè)一個(gè)執(zhí)行

1.5 并行隊(duì)列 + 異步執(zhí)行

    // 1. 并行隊(duì)列
    dispatch_queue_t queue = dispatch_queue_create("lile", DISPATCH_QUEUE_CONCURRENT);
    
    // 2. 異步執(zhí)行任務(wù)
    for (int i = 0; i < 10; i++) {
        dispatch_async(queue, ^{
            NSLog(@"%@ %d", [NSThread currentThread], i);
        });
    }

會(huì)開(kāi)很多個(gè)線程圣贸,同時(shí)執(zhí)行

1.6 主隊(duì)列 + 同步執(zhí)行

     // 1. 主隊(duì)列:專門負(fù)責(zé)在主線程上調(diào)度任務(wù)挚歧,不會(huì)在子線程調(diào)度任務(wù),在主隊(duì)列不允許開(kāi)新線程
    dispatch_queue_t queue = dispatch_get_main_queue();
    
    // 2. 同步執(zhí)行任務(wù)
    for (int i = 0; i < 10; i++) {
        // 同步:把任務(wù)放到主隊(duì)列里旁趟,但需是馬上執(zhí)行
        dispatch_sync(queue, ^{
            NSLog(@"%@ %d", [NSThread currentThread], i);
        });
        [NSThread sleepForTimeInterval:2.0];
    }

??會(huì)發(fā)生死鎖哦昼激!

1.7 主隊(duì)列 + 異步執(zhí)行

// 1. 獲得主隊(duì)列-> 程序啟動(dòng)庇绽,--> 至少有一個(gè)主線程-> 一開(kāi)始就會(huì)創(chuàng)建主隊(duì)列
    dispatch_queue_t queue = dispatch_get_main_queue();
    
    NSLog(@"1----");
    
    // 2. 異步執(zhí)行任務(wù)
    for (int i = 0; i < 10; i++) {
        NSLog(@"調(diào)度前---");
        // 異步:把任務(wù)放到主隊(duì)列里锡搜,但是不需要馬上執(zhí)行
        dispatch_async(queue, ^{
            NSLog(@"%@ %d", [NSThread currentThread], i);
        });
        [NSThread sleepForTimeInterval:2.0];
    }

不開(kāi)線程, 只能在主線程上面瞧掺,順序執(zhí)行!

1.8 全局隊(duì)列

    // 獲得全局隊(duì)列
    /**
     參數(shù):第一個(gè)參數(shù)耕餐,一般 寫 0(可以適配 iOS 7 & 8)
     iOS 7
     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í)
     
     iOS 8
     QOS_CLASS_DEFAULT  0
     
     第二個(gè)參數(shù):保留參數(shù) 0
     */
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    
    // 添加異步任務(wù)
    for (int i = 0; i < 10; i++) {
        dispatch_async(queue, ^{
            NSLog(@"%@ %d", [NSThread currentThread], i);
        });
    }

開(kāi)子線程,在子線程中無(wú)序執(zhí)行

Tip: 全局隊(duì)列和并行隊(duì)列的區(qū)別:

全局隊(duì)列沒(méi)有名稱辟狈,并發(fā)隊(duì)列有名字
全局隊(duì)列是供所有的應(yīng)用程序共享
在在MRC開(kāi)發(fā)肠缔,并發(fā)隊(duì)列夏跷,創(chuàng)建完了,需要釋放明未。 全局隊(duì)列不需要我們管理

2. 一些特殊的使用場(chǎng)景

2.1 同步任務(wù)的使用場(chǎng)景

    // 并發(fā)隊(duì)列
    dispatch_queue_t  queue = dispatch_queue_create("lile", DISPATCH_QUEUE_CONCURRENT);
    
    /**
     例子:有一個(gè)小說(shuō)網(wǎng)站
     - 必須登錄槽华,才能下載小說(shuō)
     
     有三個(gè)任務(wù):
     1. 用戶登錄
     2. 下載小說(shuō)A
     3. 下載小說(shuō)B
     */
    // 添加任務(wù)
    // 同步任務(wù),需要馬上執(zhí)行趟妥。 不開(kāi)新線程
    dispatch_sync(queue, ^{
        NSLog(@"用戶登錄 %@", [NSThread currentThread]);
    });
    // 異步任務(wù)猫态,子線程中執(zhí)行耗時(shí)操作
    dispatch_async(queue, ^{
        NSLog(@"下載小說(shuō)A %@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"下載小說(shuō)B %@", [NSThread currentThread]);
    });

關(guān)于隊(duì)列的選擇:

串行隊(duì)列異步執(zhí)行:開(kāi)一條線程,順序執(zhí)行披摄。慢亲雪,但資源占用少,省電疚膊。一般手機(jī)網(wǎng)絡(luò)時(shí)使用义辕,對(duì)性能要求不太高

并發(fā)隊(duì)列異步執(zhí)行:開(kāi)啟多條線程,同時(shí)執(zhí)行寓盗」嘧快,但資源消耗大贞让,費(fèi)電周崭。一般在WI-FI環(huán)境或需要很快響應(yīng)的場(chǎng)景下使用。

同步任務(wù):一般只會(huì)在并發(fā)隊(duì)列喳张, 需要阻塞后續(xù)任務(wù)续镇。必須等待同步任務(wù)執(zhí)行完畢,再去執(zhí)行其他任務(wù)销部。存在"依賴"關(guān)系摸航。

2.2 延時(shí)操作

    /**
     NSEC_PER_SEC: 很大的數(shù)字
     */
    dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC));
    
    /**
     多長(zhǎng)時(shí)間后執(zhí)行任務(wù)

     @param when 表示從現(xiàn)在開(kāi)始,經(jīng)過(guò)多少納秒以后
     @param queue 在那個(gè)隊(duì)列中執(zhí)行任務(wù)
     @param block 待執(zhí)行的任務(wù)
     */
    dispatch_after(when, dispatch_get_global_queue(0, 0), ^{
        NSLog(@" %@", [NSThread currentThread]);
    });

2.3 調(diào)度組(分組)

     /**
     應(yīng)用場(chǎng)景:
     開(kāi)發(fā)的時(shí)候舅桩,有的時(shí)候出現(xiàn)多個(gè)網(wǎng)絡(luò)請(qǐng)求都完成以后(每一個(gè)網(wǎng)絡(luò)請(qǐng)求的事件長(zhǎng)短不一定)酱虎,再統(tǒng)一通知用戶
     
     比如: 下載小說(shuō):三國(guó)演義, 紅樓夢(mèng)擂涛, 金X梅
     */
    // 實(shí)例化一個(gè)調(diào)度組
    dispatch_group_t group = dispatch_group_create();
    
    // 隊(duì)列
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    
    // 任務(wù)添加到隊(duì)列queue
    dispatch_group_async(group, queue, ^{
        NSLog(@"下載小說(shuō)A---%@", [NSThread currentThread]);
    });
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"下載小說(shuō)B---%@", [NSThread currentThread]);
    });
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"下載小說(shuō)X---%@", [NSThread currentThread]);
    });
    
    // 獲得所有調(diào)度組里面的異步任務(wù)完成的通知
    dispatch_group_notify(group, queue, ^{
        NSLog(@"下載完成读串,請(qǐng)觀看%@", [NSThread currentThread]); // 異步的
    });

    //注意點(diǎn): 在調(diào)度組完成通知里,可以跨隊(duì)列通信
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        // 更新UI撒妈,在主線程
        NSLog(@"下載完成恢暖,請(qǐng)觀看%@", [NSThread currentThread]); // 異步的
    });

2.4 一次性執(zhí)行

多用于創(chuàng)建單例

    static dispatch_once_t onceToken;
    NSLog(@"%ld", onceToken);
    dispatch_once(&onceToken, ^{
        NSLog(@"%----ld", onceToken);
        NSLog(@"真的執(zhí)行一次么?");
    });
    NSLog(@"完成");

3. GCD中線程間的通信

    // 全局隊(duì)列 + 異步任務(wù)
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        
        NSLog(@"%@", [NSThread currentThread]);
        // 耗時(shí)操作: 放在全局隊(duì)列狰右,異步執(zhí)行
        // 1. url, 確定一個(gè)網(wǎng)絡(luò)上的資源路徑
        NSURL *url = [NSURL URLWithString:@"http://fe.topit.me/e/d1/12/1170068721aa112d1el.jpg"];
        
        // 2. 通過(guò)url可以下載對(duì)應(yīng)的網(wǎng)絡(luò)資源, 網(wǎng)絡(luò)資源傳輸?shù)亩际嵌M(jìn)制
        NSData *data = [NSData dataWithContentsOfURL:url];
        
        // 3. 二進(jìn)制轉(zhuǎn)成圖片
        UIImage *image = [UIImage imageWithData:data];
        
        // 4. 更新UI杰捂,在主線程-》 直接把任務(wù)添加到主隊(duì)列,就會(huì)在主隊(duì)列執(zhí)行
        dispatch_async(dispatch_get_main_queue(), ^{
            self.iconView.image = image;
            NSLog(@"-----%@", [NSThread currentThread]);
        });
    });
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末棋蚌,一起剝皮案震驚了整個(gè)濱河市嫁佳,隨后出現(xiàn)的幾起案子挨队,更是在濱河造成了極大的恐慌,老刑警劉巖蒿往,帶你破解...
    沈念sama閱讀 217,084評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盛垦,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡瓤漏,警方通過(guò)查閱死者的電腦和手機(jī)情臭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)赌蔑,“玉大人俯在,你說(shuō)我怎么就攤上這事⊥薰撸” “怎么了跷乐?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,450評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)趾浅。 經(jīng)常有香客問(wèn)我愕提,道長(zhǎng),這世上最難降的妖魔是什么皿哨? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,322評(píng)論 1 293
  • 正文 為了忘掉前任浅侨,我火速辦了婚禮,結(jié)果婚禮上证膨,老公的妹妹穿的比我還像新娘如输。我一直安慰自己,他們只是感情好央勒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布不见。 她就那樣靜靜地躺著,像睡著了一般崔步。 火紅的嫁衣襯著肌膚如雪稳吮。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,274評(píng)論 1 300
  • 那天井濒,我揣著相機(jī)與錄音灶似,去河邊找鬼。 笑死瑞你,一個(gè)胖子當(dāng)著我的面吹牛酪惭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播捏悬,決...
    沈念sama閱讀 40,126評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼撞蚕,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼润梯!你這毒婦竟也來(lái)了过牙?” 一聲冷哼從身側(cè)響起甥厦,我...
    開(kāi)封第一講書(shū)人閱讀 38,980評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎寇钉,沒(méi)想到半個(gè)月后刀疙,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,414評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡扫倡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評(píng)論 3 334
  • 正文 我和宋清朗相戀三年谦秧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片撵溃。...
    茶點(diǎn)故事閱讀 39,773評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡疚鲤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出缘挑,到底是詐尸還是另有隱情集歇,我是刑警寧澤,帶...
    沈念sama閱讀 35,470評(píng)論 5 344
  • 正文 年R本政府宣布语淘,位于F島的核電站诲宇,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏惶翻。R本人自食惡果不足惜姑蓝,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評(píng)論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望吕粗。 院中可真熱鬧纺荧,春花似錦、人聲如沸颅筋。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,713評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)垃沦。三九已至客给,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間肢簿,已是汗流浹背靶剑。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,852評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留池充,地道東北人桩引。 一個(gè)月前我還...
    沈念sama閱讀 47,865評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像收夸,于是被迫代替她去往敵國(guó)和親坑匠。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評(píng)論 2 354

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

  • 從哪說(shuō)起呢卧惜? 單純講多線程編程真的不知道從哪下嘴厘灼。夹纫。 不如我直接引用一個(gè)最簡(jiǎn)單的問(wèn)題,以這個(gè)作為切入點(diǎn)好了 在ma...
    Mr_Baymax閱讀 2,757評(píng)論 1 17
  • 目錄: 1.GCD簡(jiǎn)介2.串行隊(duì)列 + 同步執(zhí)行3.串行隊(duì)列 + 異步執(zhí)行4.并發(fā)隊(duì)列 + 同步執(zhí)行5.并發(fā)隊(duì)列 ...
    倫倫子_f7b3閱讀 304評(píng)論 0 0
  • IOS---多線程實(shí)現(xiàn)方案二 (GCD) 上篇文章討論了使用PTHread和NSThread的多線程實(shí)現(xiàn)设凹。這篇文章...
    3099d00a659e閱讀 913評(píng)論 1 49
  • 背景 擔(dān)心了兩周的我終于輪到去醫(yī)院做胃鏡檢查了舰讹!去的時(shí)候我都想好了最壞的可能(胃癌),之前在網(wǎng)上查的癥狀都很相似闪朱。...
    Dely閱讀 9,237評(píng)論 21 42
  • 現(xiàn)在在一般家庭中月匣,水果的用量越來(lái)越大,飲食安排以“五果為助”奋姿,這是由溫飽型向小康型轉(zhuǎn)變的一個(gè)標(biāo)志锄开。水果中含有人體需...
    農(nóng)場(chǎng)信息閱讀 173評(píng)論 0 1