GCD

簡(jiǎn)介

  • 什么是GCD 那伐?

全稱是Grand Central Dispatch, 可譯為“牛逼的中樞調(diào)度器”灯萍,純C語(yǔ)言蕉鸳,提供了非常多強(qiáng)大的函數(shù)骇扇。

  • GCD 的優(yōu)勢(shì)

1)GCD 是蘋果公司為多核的并行運(yùn)算提出的解決方案
2)GCD 會(huì)自動(dòng)利用更多的 CPU 內(nèi)核(比如雙核映砖、四核)
3)GCD 會(huì)自動(dòng)管理線程的聲明周期(創(chuàng)建線程间坐、調(diào)度任務(wù)、銷毀線程)
4)程序員只需要告訴GCD想要執(zhí)行什么任務(wù)邑退,不需要編寫任何線程管理代碼

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

1)任務(wù):執(zhí)行什么操作
2)隊(duì)列:用來(lái)存放任務(wù)

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

1)定制任務(wù)(確定想做的事情?)
2)將任務(wù)添加到隊(duì)列中(GCD會(huì)自動(dòng)將隊(duì)列中的任務(wù)取出竹宋,放到對(duì)應(yīng)的線程中執(zhí)行。任務(wù)的取出遵循隊(duì)列的FIFO原則:先進(jìn)先出地技,后進(jìn)后出)

  • CGD中有2個(gè)用來(lái)執(zhí)行任務(wù)的常用函數(shù)

1)用同步的方式執(zhí)行任務(wù)

// queue: 隊(duì)列
// block: 任務(wù)
dispatch_sync(dispatch_queue_t queue, DISPATCH_NOESCAPE dispatch_block_t block);
  1. 異步的方式執(zhí)行任務(wù)
dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
  • 同步和異步的區(qū)別

1)同步:只能在當(dāng)前的線程中執(zhí)行任務(wù)蜈七,不具備開啟新線程的能力
2)異步:可以在新的線程中執(zhí)行任務(wù),具備開啟新線程的能力

  • GCD 中還有個(gè)用來(lái)執(zhí)行任務(wù)的函數(shù):
dispatch_barrier_sync(dispatch_queue_t queue, DISPATCH_NOESCAPE dispatch_block_t block);

在前面的任務(wù)執(zhí)行結(jié)束后它才執(zhí)行莫矗,而且它后面的任務(wù)等它執(zhí)行完成后才會(huì)執(zhí)行
這個(gè)queue不能是全局并發(fā)隊(duì)列

隊(duì)列的類型

  • GCD的隊(duì)列可以分為2大類型
  1. 并發(fā)隊(duì)列(Concurrent Dispatch Queue)
  1. 可以讓多個(gè)任務(wù)并發(fā)(同時(shí))執(zhí)行(自動(dòng)開啟多個(gè)線程同時(shí)執(zhí)行任務(wù))
    2)并發(fā)功能只有在異步(dispatch_async)函數(shù)下才有效
  1. 串行隊(duì)列(Serial Dispatch Queue)
    讓任務(wù)一個(gè)接著一個(gè)地去執(zhí)行(一個(gè)任務(wù)執(zhí)行完畢后宪潮,再執(zhí)行下一個(gè)任務(wù))

容易混淆的術(shù)語(yǔ)

  • 有4個(gè)術(shù)語(yǔ)比較容易混淆:同步、異步趣苏、并發(fā)狡相、串行
  1. 同步和異步主要影響:能不能開啟新的線程

同步: 只有在當(dāng)前線程中執(zhí)行任務(wù),不具備開啟新線程的能力
異步: 可以在新的線程中執(zhí)行任務(wù)食磕,具備開啟新線程的能力

  1. 并發(fā)和串行主要影響:任務(wù)的執(zhí)行方式

并發(fā):允許多個(gè)任務(wù)并發(fā)(同時(shí))執(zhí)行
串行:一個(gè)任務(wù)執(zhí)行完畢后尽棕,再執(zhí)行下一個(gè)任務(wù)

并發(fā)隊(duì)列

  • 使用 dispatch_queue_create 函數(shù)創(chuàng)建隊(duì)列
// label 隊(duì)列名稱
// attr  隊(duì)列的類型
dispatch_queue_t
dispatch_queue_create(const char *_Nullable label,
        dispatch_queue_attr_t _Nullable attr);
  • 創(chuàng)建并發(fā)隊(duì)列
dispatch_queue_create("com.520.queue", DISPATCH_QUEUE_CONCURRENT);
  • GCD默認(rèn)已經(jīng)提供了全局的并發(fā)隊(duì)列,供整個(gè)應(yīng)用使用彬伦,可以無(wú)需手動(dòng)創(chuàng)建

使用dispatch_get_global_queue函數(shù)獲得全局的并發(fā)隊(duì)列

// long identifier: dispatch_queue_priority_t prioity 隊(duì)列的優(yōu)先級(jí)
// flags 此參數(shù)暫時(shí)無(wú)用滔悉,用0即可
dispatch_queue_t
dispatch_get_global_queue(long identifier, unsigned long flags);
  • 獲得全局并發(fā)隊(duì)列
dispatch_queue queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)
  • 全局并發(fā)隊(duì)列的優(yōu)先級(jí)
#define DISPATCH_QUEUE_PRIORITY_HIGH 2                // 高
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0             // 默認(rèn)(中)
#define DISPATCH_QUEUE_PRIORITY_LOW (-2)              // 低
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN  // 后臺(tái)

串行隊(duì)列

  • GCD中獲取串行有2種途徑

使用 dispatch_queue_create 函數(shù)創(chuàng)建隊(duì)列

// 創(chuàng)建串行隊(duì)列(隊(duì)列類型傳遞NULL或者DISPATCH_QUEUE_SERIAL)
    dispatch_queue_t queue = dispatch_queue_create("com.520.queue", DISPATCH_QUEUE_SERIAL);
  • 使用主隊(duì)列 (跟主線程相關(guān)聯(lián)的隊(duì)列)

1) 主隊(duì)列是 GCD 自帶的一種特殊的串行隊(duì)列
2) 放在主隊(duì)列的任務(wù),都會(huì)放在主線程中執(zhí)行
3) 使用 dispatch_get_main_queue()獲得主隊(duì)列

dispatch_queue_t queue = dispatch_get_main_queue();

各種隊(duì)列的執(zhí)行效果

使用sync函數(shù)往當(dāng)前串行隊(duì)列中添加任務(wù)单绑,會(huì)卡住當(dāng)前的串行隊(duì)列

線程間通信示例

  • 從子線程回到主線程
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // 執(zhí)行耗時(shí)的異步操作...
      dispatch_async(dispatch_get_main_queue(), ^{
        // 回到主線程回官,執(zhí)行UI刷新操作
        });
});

延時(shí)執(zhí)行

  • iOS常見(jiàn)的延時(shí)方法
  1. 調(diào)用NSObject的方法
    [self performSelector:@selector(run) withObject:nil afterDelay:2.0];
    // 2秒后再調(diào)用self的run方法

  2. 使用GCD函數(shù)
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    // 2秒后執(zhí)行這里的代碼...
    });

  3. 使用NSTimer
    [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(test) userInfo:nil repeats:NO];

一次性代碼

  • 使用dispatch_once函數(shù)能保證某段代碼在程序運(yùn)行過(guò)程中只被執(zhí)行1次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    // 只執(zhí)行1次的代碼(這里面默認(rèn)是線程安全的)
});

快速迭代

  • 使用 dispatch_apply函數(shù)能進(jìn)行快速迭代遍歷
dispatch_apply(10, dispatch_get_global_queue(0, 0), ^(size_t index){
    // 執(zhí)行10次代碼,index順序不確定
});

組隊(duì)列

  • 有這樣一種需求

首先:分別異步執(zhí)行2個(gè)耗時(shí)的操作
其次:等2個(gè)異步操作都執(zhí)行完畢后搂橙,再回到主線程執(zhí)行操作

如果想要快速高效地實(shí)現(xiàn)上述需求歉提,可以考慮用隊(duì)列組

dispatch_group_t group =  dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // 執(zhí)行1個(gè)耗時(shí)的異步操作
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // 執(zhí)行1個(gè)耗時(shí)的異步操作
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    // 等前面的異步操作都執(zhí)行完畢后,回到主線程...
});
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市苔巨,隨后出現(xiàn)的幾起案子版扩,更是在濱河造成了極大的恐慌,老刑警劉巖侄泽,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件礁芦,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡悼尾,警方通過(guò)查閱死者的電腦和手機(jī)柿扣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)闺魏,“玉大人未状,你說(shuō)我怎么就攤上這事∠鲜ぃ” “怎么了娩践?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)烹骨。 經(jīng)常有香客問(wèn)我翻伺,道長(zhǎng),這世上最難降的妖魔是什么沮焕? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任吨岭,我火速辦了婚禮,結(jié)果婚禮上峦树,老公的妹妹穿的比我還像新娘辣辫。我一直安慰自己,他們只是感情好魁巩,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布急灭。 她就那樣靜靜地躺著,像睡著了一般谷遂。 火紅的嫁衣襯著肌膚如雪葬馋。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天肾扰,我揣著相機(jī)與錄音畴嘶,去河邊找鬼。 笑死集晚,一個(gè)胖子當(dāng)著我的面吹牛窗悯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播偷拔,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蒋院,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼亏钩!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起悦污,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤铸屉,失蹤者是張志新(化名)和其女友劉穎钉蒲,沒(méi)想到半個(gè)月后切端,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡顷啼,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年踏枣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片钙蒙。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡茵瀑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出躬厌,到底是詐尸還是另有隱情马昨,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布扛施,位于F島的核電站鸿捧,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏疙渣。R本人自食惡果不足惜匙奴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望妄荔。 院中可真熱鬧泼菌,春花似錦、人聲如沸啦租。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)篷角。三九已至焊刹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間内地,已是汗流浹背伴澄。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留阱缓,地道東北人非凌。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像荆针,于是被迫代替她去往敵國(guó)和親敞嗡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子颁糟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

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