iOS之淺談GCD

GCD的基本思想


  • GCD的基本思想是將操作放在隊(duì)列中去執(zhí)行
    (1)操作使用block定義睁搭。
    (2)隊(duì)列負(fù)責(zé)調(diào)度任務(wù)執(zhí)行所在的線程以及具體的執(zhí)行時(shí)間。
    (3)隊(duì)列的特點(diǎn)是先進(jìn)先出想许,新添加到隊(duì)列的操作排在最后慰技。
  • 隊(duì)列 dispatch_queue_t
    (1) DISPATCH_QUEUE_SERIAL:串行隊(duì)列,隊(duì)列中的任務(wù)只會(huì)順序執(zhí)行娘摔。
    (2) DISPATCH_QUEUE_CONCURRENT:并行隊(duì)列,隊(duì)列中的任務(wù)通常會(huì)并發(fā)執(zhí)行唤反。
  • 操作
    dispatch_async 異步操作凳寺,會(huì)并發(fā)執(zhí)行,不會(huì)順序執(zhí)行彤侍。
    dispatch_sync 同步操作肠缨,會(huì)依次順序執(zhí)行,能決定任務(wù)執(zhí)行的順序盏阶。

一晒奕、DISPATCH_QUEUE_SERIAL: 串行隊(duì)列:
- (void) GCD
{

//DISPATCH_QUEUE_SERIAL串行隊(duì)列,會(huì)死鎖,但是會(huì)執(zhí)行嵌套同步操作之前的代碼
dispatch_queue_t queue = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);

dispatch_async(queue, ^{
    NSLog(@"讀書===%@", [NSThread currentThread]);
});

dispatch_async(queue, ^{
    NSLog(@"吃飯====%@", [NSThread currentThread]);
});

dispatch_async(queue, ^{
    NSLog(@"上廁所====%@", [NSThread currentThread]);
}); 
}

2016-04-13 16:24:22.100 test[25089:1136445] 讀書===<NSThread: 0x7fb050700ee0>{number = 2, name = (null)}
2016-04-13 16:24:22.101 test[25089:1136445] 吃飯====<NSThread: 0x7fb050700ee0>{number = 2, name = (null)}
2016-04-13 16:24:22.102 test[25089:1136445] 上廁所====<NSThread: 0x7fb050700ee0>{number = 2, name = (null)} 

可以看出來(lái)當(dāng)操作方式是dispatch_async時(shí)脑慧,只有兩個(gè)隊(duì)列魄眉,一個(gè)主線程,一個(gè)子線程闷袒,在子線程中執(zhí)行三個(gè)方法坑律,所以異步操作是可以創(chuàng)建新線程的,而且操作會(huì)順序執(zhí)行的囊骤,這個(gè)非常有用晃择,既不會(huì)影響主線程,又可以開啟新線程按順序執(zhí)行任務(wù)∫参铮現(xiàn)在把操作方式改為dispatch_sync看一下打印結(jié)果:

2016-04-13 17:33:42.131 test[25342:1168870] 讀書===<NSThread: 0x7f8118d03bb0>{number = 1, name = main}
2016-04-13 17:33:42.131 test[25342:1168870] 吃飯====<NSThread: 0x7f8118d03bb0>{number = 1, name = main}
2016-04-13 17:33:42.132 test[25342:1168870] 上廁所====<NSThread: 0x7f8118d03bb0>{number = 1, name = main}

可以看出來(lái)只有一個(gè)線程宫屠,也就是主線程,所以證明了dispatch_sync是沒有開啟新線程的能力的滑蚯。

二浪蹂、DISPATCH_QUEUE_CONCURRENT:并行隊(duì)列

我們?cè)侔殃?duì)列的屬性改成DISPATCH_QUEUE_CONCURRENT試試,看下打印結(jié)果:

2016-04-13 17:44:38.296 test[25402:1175291] 上廁所====<NSThread: 0x7fdfe8f288a0>{number = 4, name = (null)}
2016-04-13 17:44:38.296 test[25402:1175301] 讀書===<NSThread: 0x7fdfe8f2bf10>{number = 2, name = (null)}
2016-04-13 17:44:38.296 test[25402:1175307] 吃飯====<NSThread: 0x7fdfe8e21cd0>{number = 3, name = (null)}

首先告材,可以看出乌逐,當(dāng)隊(duì)列的屬性是DISPATCH_QUEUE_CONCURRENT時(shí),任務(wù)會(huì)無(wú)序執(zhí)行的创葡,而且并行隊(duì)列DISPATCH_QUEUE_CONCURRENT是可以開啟新線程的。

得出結(jié)果當(dāng)隊(duì)列的屬性是DISPATCH_QUEUE_CONCURRENT并行隊(duì)列绢慢,操作是異步操作dispatch_async時(shí)灿渴,會(huì)創(chuàng)建多個(gè)線程,操作無(wú)序執(zhí)行胰舆。但是如果隊(duì)列錢有其他任務(wù)骚露,會(huì)等待其他任務(wù)執(zhí)行完成后再執(zhí)行其他的任務(wù)。適合的操作為:既不影響主線程缚窿,又不需要順序執(zhí)行的操作棘幸。

然后,我們?cè)侔巡僮鞲臑閐ispatch_sync,看下打印結(jié)果:

2016-04-13 18:08:17.944 test[25521:1187204] 讀書===<NSThread: 0x7fe74ac05610>{number = 1, name = main}
2016-04-13 18:08:17.944 test[25521:1187204] 吃飯====<NSThread: 0x7fe74ac05610>{number = 1, name = main}
2016-04-13 18:08:17.945 test[25521:1187204] 上廁所====<NSThread: 0x7fe74ac05610>{number = 1, name = main}

可以看出倦零,無(wú)論隊(duì)列的方式是串行隊(duì)列還是并行隊(duì)列误续,dispatch_sync同步操作方式都是不會(huì)創(chuàng)建新線程的,任務(wù)只會(huì)在主線程中執(zhí)行扫茅。

三蹋嵌、dispatch_get_global_queue():全局隊(duì)列

看下面一段代碼:
- (void) globalQueue
{
//全局隊(duì)列,都在主線程中執(zhí)行葫隙,不會(huì)死鎖栽烂,
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
NSLog(@"讀書===%@", [NSThread currentThread]);
});

dispatch_async(queue, ^{
    NSLog(@"吃飯====%@", [NSThread currentThread]);
});

dispatch_async(queue, ^{
    NSLog(@"上廁所====%@", [NSThread currentThread]);
});
}

結(jié)果:

2016-04-13 18:16:18.646 test[25609:1191848] 吃飯====<NSThread: 0x7f91c940db00>{number = 3, name = (null)}
2016-04-13 18:16:18.650 test[25609:1191841] 讀書===<NSThread: 0x7f91c9659890>{number = 2, name = (null)}
2016-04-13 18:16:18.646 test[25609:1191855] 上廁所====<NSThread: 0x7f91c940fa50>{number = 4, name = (null)}

全局隊(duì)列是系統(tǒng)的,無(wú)序創(chuàng)建,直接用即可腺办,可以看出焰手,全局隊(duì)列與并行隊(duì)列類型,但是調(diào)試時(shí)怀喉,無(wú)法確認(rèn)操作所在隊(duì)列书妻。
當(dāng)操作方式為dispatch_sync時(shí),不再做解析磺送,雷同上面驻子。

四、dispatch_get_main_queue():主隊(duì)列

看下面一段代碼:

- (void) mainQueue
{
//直接死鎖
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
    NSLog(@"讀書===%@", [NSThread currentThread]);
});

dispatch_async(queue, ^{
    NSLog(@"吃飯====%@", [NSThread currentThread]);
});

dispatch_async(queue, ^{
    NSLog(@"上廁所====%@", [NSThread currentThread]);
});
}

結(jié)果:

2016-04-13 18:35:50.259 test[25749:1204150] 讀書===<NSThread: 0x7fc9f8e05c30>{number = 1, name = main}
2016-04-13 18:35:50.264 test[25749:1204150] 吃飯====<NSThread: 0x7fc9f8e05c30>{number = 1, name = main}
2016-04-13 18:35:50.264 test[25749:1204150] 上廁所====<NSThread: 0x7fc9f8e05c30>{number = 1, name = main}

每一個(gè)應(yīng)用程序中只有一個(gè)主隊(duì)列估灿,直接使用即可無(wú)需創(chuàng)建崇呵,常常在主隊(duì)列中更新UI。主隊(duì)列中的操作都應(yīng)該自主隊(duì)列中執(zhí)行馅袁,不存在異步的概念域慷。除非主線程被用戶殺掉,否則永遠(yuǎn)不會(huì)結(jié)束汗销。

五犹褒、dispatch_sync的應(yīng)用場(chǎng)景(登陸操作)。dispatch_sync會(huì)阻塞并行隊(duì)列的執(zhí)行弛针,要求某一操作執(zhí)行完成之后才會(huì)執(zhí)行下一個(gè)操作叠骑。
- (void) newThread
{
dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo", DISPATCH_QUEUE_CONCURRENT);
__block BOOL logon = NO;
dispatch_sync(q, ^{ //同步
    NSLog(@"模擬耗時(shí)操作 %@", [NSThread currentThread]);
    [NSThread sleepForTimeInterval:2.0f];//停留兩秒鐘,模仿耗時(shí)操作
    NSLog(@"模擬耗時(shí)完成 %@", [NSThread currentThread]);
    logon = YES;
});

dispatch_async(q, ^{
    NSLog(@"登錄完成的處理 %@", [NSThread currentThread]);
});
}

結(jié)果:

2016-04-14 10:47:24.117 test[26976:1276763] 模擬耗時(shí)操作 <NSThread: 0x7fe3a8d054e0>{number = 1, name = main}
2016-04-14 10:47:26.119 test[26976:1276763] 模擬耗時(shí)完成 <NSThread: 0x7fe3a8d054e0>{number = 1, name = main}
2016-04-14 10:47:26.119 test[26976:1276894] 登錄完成的處理 <NSThread: 0x7fe3a8c10f80>{number = 2, name = (null)}
六削茁、dispatch_barrier_async,在并行隊(duì)列中等待前面的操作執(zhí)行完成后宙枷,才恢復(fù)后面的執(zhí)行狀態(tài)。
- (void) dispatchBarrierAsync
{
dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^(){
    NSLog(@"%@====dispatch-1", [NSThread currentThread]);
});
dispatch_async(concurrentQueue, ^(){
    NSLog(@"%@=====dispatch-2", [NSThread currentThread]);
});
dispatch_barrier_async(concurrentQueue, ^(){
    NSLog(@"%@======dispatch-barrier", [NSThread currentThread]);
});
dispatch_async(concurrentQueue, ^(){
    NSLog(@"%@======dispatch-3", [NSThread currentThread]);
});
dispatch_async(concurrentQueue, ^(){
    NSLog(@"%@======dispatch-4", [NSThread currentThread]);
});
}

結(jié)果:

2016-04-14 11:00:34.769 test[27143:1285750] <NSThread: 0x7ff80a70adb0>{number = 3, name = (null)}=====dispatch-2
2016-04-14 11:00:34.769 test[27143:1285758] <NSThread: 0x7ff80a40f460>{number = 2, name = (null)}====dispatch-1
2016-04-14 11:00:34.772 test[27143:1285758] <NSThread: 0x7ff80a40f460>{number = 2, name = (null)}======dispatch-barrier
2016-04-14 11:00:34.772 test[27143:1285758] <NSThread: 0x7ff80a40f460>{number = 2, name = (null)}======dispatch-3
2016-04-14 11:00:34.772 test[27143:1285750] <NSThread: 0x7ff80a70adb0>{number = 3, name = (null)}======dispatch-4
七茧跋、dispatch_group_t慰丛,當(dāng)有多個(gè)任務(wù)時(shí),可以把多個(gè)任務(wù)放到group里面瘾杭,group執(zhí)行完畢后再執(zhí)行其他任務(wù)诅病。
- (void) group
{
dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
    
    NSLog(@"task1 begin=====%@", [NSThread currentThread]);
});

dispatch_group_async(group, queue, ^{
    
    NSLog(@"task2 begin=====%@", [NSThread currentThread]);
});
dispatch_group_notify(group, queue, ^{
    NSLog(@"======================%@", [NSThread currentThread]);
});
dispatch_group_async(group, queue, ^{
    
    NSLog(@"task3 begin=====%@", [NSThread currentThread]);
});

dispatch_group_async(group, queue, ^{
    
    NSLog(@"task4 begin=====%@", [NSThread currentThread]);
});
}

結(jié)果:

2016-04-14 11:35:54.676 test[27339:1300173] task1 begin=====<NSThread: 0x7fe3da606170>{number = 2, name = (null)}
2016-04-14 11:35:54.729 test[27339:1300202] task4 begin=====<NSThread: 0x7fe3da621660>{number = 5, name = (null)}
2016-04-14 11:35:54.729 test[27339:1300167] task2 begin=====<NSThread: 0x7fe3da6213a0>{number = 3, name = (null)}
2016-04-14 11:35:54.729 test[27339:1300178] task3 begin=====<NSThread: 0x7fe3da51f7b0>{number = 4, name = (null)}
2016-04-14 11:35:54.770 test[27339:1300178] ======================<NSThread: 0x7fe3da51f7b0>{number = 4, name = (null)}

可以看出,當(dāng)所有任務(wù)都執(zhí)行完畢后才執(zhí)行dispatch_group_notify中的任務(wù)粥烁。

看完這篇文章贤笆,相信大家對(duì)GCD有了詳細(xì)的了解,有問題歡迎大家一起探討页徐,下班回家吃飯去苏潜,哈哈。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末变勇,一起剝皮案震驚了整個(gè)濱河市恤左,隨后出現(xiàn)的幾起案子贴唇,更是在濱河造成了極大的恐慌,老刑警劉巖飞袋,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件戳气,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡巧鸭,警方通過查閱死者的電腦和手機(jī)瓶您,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)纲仍,“玉大人呀袱,你說我怎么就攤上這事≈5” “怎么了夜赵?”我有些...
    開封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)乡革。 經(jīng)常有香客問我寇僧,道長(zhǎng),這世上最難降的妖魔是什么沸版? 我笑而不...
    開封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任嘁傀,我火速辦了婚禮,結(jié)果婚禮上视粮,老公的妹妹穿的比我還像新娘细办。我一直安慰自己,他們只是感情好蕾殴,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開白布蟹腾。 她就那樣靜靜地躺著,像睡著了一般区宇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上值戳,一...
    開封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天议谷,我揣著相機(jī)與錄音,去河邊找鬼堕虹。 笑死卧晓,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的赴捞。 我是一名探鬼主播逼裆,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼赦政!你這毒婦竟也來(lái)了胜宇?” 一聲冷哼從身側(cè)響起耀怜,我...
    開封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎桐愉,沒想到半個(gè)月后财破,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡左痢,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了系洛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片俊性。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖描扯,靈堂內(nèi)的尸體忽然破棺而出定页,到底是詐尸還是另有隱情,我是刑警寧澤荆烈,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布拯勉,位于F島的核電站,受9級(jí)特大地震影響憔购,放射性物質(zhì)發(fā)生泄漏宫峦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一玫鸟、第九天 我趴在偏房一處隱蔽的房頂上張望导绷。 院中可真熱鬧,春花似錦屎飘、人聲如沸妥曲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)檐盟。三九已至,卻和暖如春押桃,著一層夾襖步出監(jiān)牢的瞬間葵萎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工唱凯, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留羡忘,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓磕昼,卻偏偏與公主長(zhǎng)得像卷雕,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子票从,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

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

  • 簡(jiǎn)介 GCD(Grand Central Dispatch)是在macOS10.6提出來(lái)的漫雕,后來(lái)在iOS4.0被引...
    sunmumu1222閱讀 864評(píng)論 0 2
  • iOS中GCD的使用小結(jié) 作者dullgrass 2015.11.20 09:41*字?jǐn)?shù) 4996閱讀 20199...
    DanDanC閱讀 829評(píng)論 0 0
  • 目錄(GCD): 關(guān)鍵詞 混淆點(diǎn) 場(chǎng)景應(yīng)用 總結(jié) 1. 關(guān)鍵詞 線程概念: 獨(dú)立執(zhí)行的代碼段滨嘱,一個(gè)線程同時(shí)間只能執(zhí)...
    Ryan___閱讀 1,271評(píng)論 0 3
  • 本篇博客共分以下幾個(gè)模塊來(lái)介紹GCD的相關(guān)內(nèi)容: 多線程相關(guān)概念 多線程編程技術(shù)的優(yōu)缺點(diǎn)比較? GCD中的三種隊(duì)列...
    有夢(mèng)想的老伯伯閱讀 1,020評(píng)論 0 4
  • 1. GCD簡(jiǎn)介 什么是GCD呢蝎亚?我們先來(lái)看看百度百科的解釋簡(jiǎn)單了解下概念 引自百度百科:Grand Centra...
    千尋_544f閱讀 365評(píng)論 0 0