iOS 多線程開(kāi)發(fā) —— GCD隊(duì)列和任務(wù)執(zhí)行方式

圖片發(fā)自簡(jiǎn)書(shū)App


GCD是iOS開(kāi)發(fā)中非常好用的線程管理方法觉啊,本篇博客會(huì)簡(jiǎn)單介紹GCD隊(duì)列和任務(wù)執(zhí)行方式的概念档泽,以代碼實(shí)驗(yàn)的方式驗(yàn)證GCD各種執(zhí)行方式與線程的關(guān)系。

GCD的介紹

GCD為Grand Central Dispatch的縮寫(xiě)辽旋。

Grand Central Dispatch (GCD)是蘋(píng)果爸爸開(kāi)發(fā)的一個(gè)多核編程的較新的解決方法珠增。它主要用于優(yōu)化應(yīng)用程序以支持多核處理器以及其他對(duì)稱(chēng)多處理系統(tǒng)。它是一個(gè)在線程池模式的基礎(chǔ)上執(zhí)行的并行任務(wù)葬馋。在Mac OS X 10.6雪豹中首次推出卖鲤,也可在iOS 4及以上版本使用。


GCD核心思想

GCD的核心思想 —— 任務(wù) 畴嘶, 隊(duì)列

隊(duì)列

隊(duì)列指的是任務(wù)隊(duì)列, 用來(lái)存放任務(wù)的隊(duì)列, 可以說(shuō)隊(duì)列是一種比較特殊的線性表, 采用的是先進(jìn)先出(FIFO)原則, 就像是出高速公路收費(fèi)站一樣, 從最前面一個(gè)開(kāi)始, 排在前面的車(chē)子交了費(fèi)先走, 才到下一個(gè), 這里的隊(duì)列分為兩種,并行隊(duì)列和串行隊(duì)列.

并行隊(duì)列:全名為Concurrent Dispatch Queue, 指的是可以讓多個(gè)任務(wù)同時(shí)執(zhí)行, 如果用到并行隊(duì)列的話(huà), 是會(huì)自動(dòng)開(kāi)啟多個(gè)線程同時(shí)執(zhí)行任務(wù).

串行隊(duì)列:全名Serial Dispatch Queue, 指的是任務(wù)一個(gè)接一個(gè)的執(zhí)行, 完成了前面的那個(gè)就到后面那個(gè), 和我們剛剛舉的收費(fèi)站例子一樣.

使用dispatch_queue_create來(lái)創(chuàng)建一個(gè)隊(duì)列蛋逾,默認(rèn)情況下創(chuàng)建的為串行隊(duì)列。如果需要?jiǎng)?chuàng)建并行隊(duì)列窗悯,需要設(shè)置DISPATCH_QUEUE_CONCURRENT区匣,設(shè)置DISPATCH_QUEUE_SERIAL為串行隊(duì)列。

注意: 并行隊(duì)列只有在異步執(zhí)行(dispatch_async)才有效.

GCD生成并行隊(duì)列和串行隊(duì)列的方法

在隊(duì)列中還有還有兩個(gè)會(huì)經(jīng)常使用到的隊(duì)列蒋院。

主隊(duì)列:dispatch_get_main_queue()

主隊(duì)列是GCD自帶的一種特殊的串行隊(duì)列亏钩,放在主隊(duì)列中得任務(wù),都會(huì)放到主線程中執(zhí)行欺旧。

全局隊(duì)列:dispatch_get_global_queue(longidentifier,unsignedlongflags)

關(guān)于全局隊(duì)列铸屉,生成一個(gè)全局隊(duì)列需要設(shè)置兩個(gè)參數(shù)。
第一個(gè)參數(shù):用來(lái)設(shè)置該隊(duì)列在整個(gè)任務(wù)執(zhí)行中的優(yōu)先級(jí)別切端。
兩者的對(duì)應(yīng)關(guān)系如下:
- DISPATCH_QUEUE_PRIORITY_HIGH
- DISPATCH_QUEUE_PRIORITY_DEFAULT
- DISPATCH_QUEUE_PRIORITY_LOW
- DISPATCH_QUEUE_PRIORITY_BACKGROUND

此處值得一提的DISPATCH_QUEUE_PRIORITY_BACKGROUND級(jí)別彻坛,被設(shè)置成后臺(tái)級(jí)別的隊(duì)列,它會(huì)等待所有比它級(jí)別高的隊(duì)列中的任務(wù)執(zhí)行完或CPU空閑的時(shí)候才會(huì)執(zhí)行自己的任務(wù)。例如磁盤(pán)的讀寫(xiě)操作非常耗時(shí)昌屉,如果我們不需要立即獲取到磁盤(pán)的數(shù)據(jù)钙蒙,我們可以把讀寫(xiě)任務(wù)放到后臺(tái)隊(duì)列中,這樣讀寫(xiě)任務(wù)只會(huì)在恰當(dāng)?shù)臅r(shí)候去執(zhí)行而不會(huì)影響需要更改優(yōu)先級(jí)的其他任務(wù)间驮,整個(gè)程序也會(huì)更加有效率躬厌。



任務(wù)

所謂的任務(wù), 就是指我們程序員放在GCD里的操作, 一般是用Block方式進(jìn)行, 這里有兩種執(zhí)行任務(wù)的操作,同步執(zhí)行和異步執(zhí)行, 兩個(gè)的區(qū)別就是在是否開(kāi)啟新線程進(jìn)行操作.

同步執(zhí)行:在GCD里是sync, 不會(huì)開(kāi)啟新線程, 只會(huì)在當(dāng)前線程進(jìn)行操作.

異步執(zhí)行:在GCD里是async, 可以另外開(kāi)啟一個(gè)新的線程執(zhí)行任務(wù).

同步執(zhí)行和異步執(zhí)行

任務(wù)執(zhí)行分為同步、異步竞帽,隊(duì)列類(lèi)型分為串行扛施、并行,所以搭配如下:
同步 + 串行屹篓;
同步 + 并行疙渣;
異步 + 串行;
異步 + 并行堆巧;

同步 + 串行 的執(zhí)行妄荔,異步 + 并行 的執(zhí)行方式比較顯而易見(jiàn),所以在此處主要針對(duì)同步 + 并行谍肤,異步 + 串行 的任務(wù)做一下實(shí)驗(yàn)驗(yàn)證啦租。


下面我們就開(kāi)始各種歡樂(lè)的實(shí)驗(yàn)吧~

同步 + 并行 操作實(shí)驗(yàn)

同步 + 并行

執(zhí)行結(jié)果

同步 + 并行執(zhí)行結(jié)果

結(jié)論:叢該實(shí)驗(yàn)中確實(shí)是證實(shí)了并行隊(duì)列在同步執(zhí)行中并不會(huì)開(kāi)辟新的線程,所有的任務(wù)都是在主線程中完成荒揣,并且任務(wù)為一個(gè)一個(gè)的串行執(zhí)行篷角。

異步 + 串行 操作實(shí)驗(yàn)

異步 + 串行

執(zhí)行結(jié)果

異步 + 串行執(zhí)行結(jié)果

從該實(shí)驗(yàn)操作中,可以看到最先開(kāi)始任務(wù)還是在主線程中執(zhí)行系任,后來(lái)異步執(zhí)行會(huì)開(kāi)辟一條新的線程用來(lái)執(zhí)行隊(duì)列中的任務(wù)内地。但是可以看出開(kāi)辟線程也是會(huì)損耗性能,所以在主線程中打印結(jié)束標(biāo)示的任務(wù)反而先打印出來(lái)赋除。

異步 + 多條串行 實(shí)驗(yàn)操作

異步 + 多條串行

執(zhí)行結(jié)果

異步 + 多條串行執(zhí)行結(jié)果

異步 + 串行 的執(zhí)行結(jié)果得到異步執(zhí)行串行隊(duì)列阱缓,是會(huì)開(kāi)辟新的線程執(zhí)行任務(wù)的,但博主不由想到開(kāi)辟線程數(shù)是否會(huì)和隊(duì)列數(shù)有關(guān)系,通過(guò) 異步 + 多條串行 操作實(shí)驗(yàn)可以得出在異步執(zhí)行情況下,會(huì)為每一條串行隊(duì)列生成一條新的線程執(zhí)行任務(wù)殖属。

異步 + 并行 實(shí)驗(yàn)操作

異步 + 并行
異步 + 并行執(zhí)行結(jié)果

從 異步 + 并行 的執(zhí)行結(jié)果,對(duì)比 異步 + 串行 執(zhí)行結(jié)果航背,在異步執(zhí)行中一定會(huì)開(kāi)辟新的線程,串行隊(duì)列開(kāi)辟了一條新線程供串行隊(duì)列中的任務(wù)一個(gè)一個(gè)的執(zhí)行棱貌,在并行隊(duì)列中為了確保隊(duì)列中的任務(wù)能盡快的執(zhí)行玖媚,異步執(zhí)行情況下為并行隊(duì)列中的每一個(gè)任務(wù)都開(kāi)辟了一條新的線程,因此可以得出節(jié)省時(shí)間的情況下婚脱,異步 + 并行 的方法是很不錯(cuò)今魔,但從打印結(jié)果可以看出開(kāi)辟線程也會(huì)消耗處理器的資源勺像。

同步 + 多隊(duì)列 實(shí)驗(yàn)操作

同步 + 多隊(duì)列
同步 + 多隊(duì)列執(zhí)行結(jié)果

同步 + 多隊(duì)列 的結(jié)果證實(shí)了同步情況下,線程數(shù)和隊(duì)列數(shù)無(wú)關(guān)错森,并不會(huì)開(kāi)辟新的線程執(zhí)行任務(wù)吟宦。同步執(zhí)行方式不會(huì)開(kāi)辟新的線程,那么同步執(zhí)行會(huì)在哪一條線程中進(jìn)行任務(wù)執(zhí)行呢涩维?為了得到答案殃姓,博主又進(jìn)行了一次下面的實(shí)驗(yàn)操作。

異步 + 多隊(duì)列 中 任務(wù)進(jìn)行 同步 執(zhí)行 實(shí)驗(yàn)操作

異步 + 多隊(duì)列 中 任務(wù)進(jìn)行 同步
異步 + 多隊(duì)列 中 任務(wù)進(jìn)行 同步執(zhí)行結(jié)果

異步 + 多隊(duì)列 中 任務(wù)進(jìn)行 同步 的實(shí)驗(yàn)結(jié)果可以看出來(lái)瓦阐,在隊(duì)列queue1的任務(wù)中我又擦入了一條并行隊(duì)列同步執(zhí)行蜗侈,系統(tǒng)為queue1隊(duì)列開(kāi)辟了線程3來(lái)執(zhí)行任務(wù),因?yàn)橥綀?zhí)行不開(kāi)辟新的線程睡蟋,因此并行隊(duì)列queue3的任務(wù)也直接在queue1的線程3中執(zhí)行了踏幻,因此可以得出同步執(zhí)行不開(kāi)辟線程,同步執(zhí)行的任務(wù)會(huì)在他正在執(zhí)行的線程中執(zhí)行薄湿。

以上做了自己創(chuàng)建的隊(duì)列在同步,異步執(zhí)行中的一些情況偷卧,可以總結(jié)為 異步 + 并行 時(shí)豺瘤,系統(tǒng)會(huì)為每個(gè)任務(wù)開(kāi)創(chuàng)一個(gè)新的線程執(zhí)行,者異步 + 串行 的情況下听诸,隊(duì)列數(shù)決定了線程數(shù)坐求。同步情況下不開(kāi)辟新的線程。

除了自己創(chuàng)建隊(duì)列執(zhí)行任務(wù)之外晌梨,系統(tǒng)也還存在著主隊(duì)列桥嗤、全局隊(duì)列直接供我們使用。

在上文中仔蝌,也提到了全局隊(duì)列dispatch_get_global_queue也屬于并行隊(duì)列泛领,博主做了全局隊(duì)列異步、同步的執(zhí)行后敛惊,執(zhí)行結(jié)果和自創(chuàng)并行隊(duì)列無(wú)異渊鞋,也不由思考全局隊(duì)列和自創(chuàng)并發(fā)隊(duì)列到底有什么卵區(qū)別呢?查閱一些資料后瞧挤,總結(jié)如下:
1锡宋,全局隊(duì)列沒(méi)有名字,但是并發(fā)隊(duì)列有名字特恬。有名字可以便于查看系統(tǒng)日志执俩;
2,全局隊(duì)列是所有應(yīng)用程序共享的癌刽;
3役首,在mrc的時(shí)候尝丐,全局隊(duì)列不用手動(dòng)釋放,但是并發(fā)隊(duì)列需要宋税;

在使用系統(tǒng)的主隊(duì)列時(shí)有一個(gè)值得一提的問(wèn)題:卡線程

同步 + 主隊(duì)列
執(zhí)行結(jié)果

以上圖片的寫(xiě)法可以看到摊崭,執(zhí)行結(jié)果在執(zhí)行第一句后就不再執(zhí)行后文了,這種情況叫做卡線程杰赛。大致原因:我們都知道, 同步執(zhí)行是一個(gè)一個(gè)任務(wù)去執(zhí)行的呢簸。但主線程還在執(zhí)行“搞事情的打印”的時(shí)候, 我們又往主線程里塞任務(wù), 這個(gè)時(shí)候就會(huì)出現(xiàn)異常現(xiàn)象乏屯。

優(yōu)化方式

避免卡線程寫(xiě)法
避免卡線程寫(xiě)法執(zhí)行結(jié)果

為了避免卡線程的情況根时,那么就先開(kāi)辟一條新的線程,然后再去執(zhí)行主隊(duì)列中的任務(wù)辰晕,這么做打印結(jié)果就正常了蛤迎,并且通過(guò)這個(gè)寫(xiě)法,也得出一個(gè)結(jié)論含友,同步執(zhí)行主隊(duì)列時(shí)替裆,任務(wù)執(zhí)行不會(huì)再保持在原線程里,而是回到了主線程中窘问,主隊(duì)列中的任務(wù)只能在主線程中執(zhí)行辆童。


總結(jié)

通過(guò)以上的各項(xiàng)實(shí)驗(yàn),對(duì)GCD隊(duì)列和任務(wù)在線程中的執(zhí)行方式有了進(jìn)一步了解惠赫,隊(duì)列和任務(wù)只是GCD最普通的用法把鉴,有時(shí)間會(huì)在關(guān)于GCD的實(shí)際使用依然以代碼實(shí)驗(yàn)的方式寫(xiě)一篇博客作為記錄。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末儿咱,一起剝皮案震驚了整個(gè)濱河市庭砍,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌混埠,老刑警劉巖怠缸,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異钳宪,居然都是意外死亡凯旭,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)使套,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)罐呼,“玉大人,你說(shuō)我怎么就攤上這事侦高〖挡瘢” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵奉呛,是天一觀的道長(zhǎng)计螺。 經(jīng)常有香客問(wèn)我夯尽,道長(zhǎng),這世上最難降的妖魔是什么登馒? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任匙握,我火速辦了婚禮,結(jié)果婚禮上陈轿,老公的妹妹穿的比我還像新娘圈纺。我一直安慰自己,他們只是感情好麦射,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布蛾娶。 她就那樣靜靜地躺著,像睡著了一般潜秋。 火紅的嫁衣襯著肌膚如雪蛔琅。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天峻呛,我揣著相機(jī)與錄音罗售,去河邊找鬼。 笑死钩述,一個(gè)胖子當(dāng)著我的面吹牛寨躁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播切距,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼朽缎,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼惨远!你這毒婦竟也來(lái)了谜悟?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤北秽,失蹤者是張志新(化名)和其女友劉穎葡幸,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體贺氓,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蔚叨,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了辙培。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蔑水。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖扬蕊,靈堂內(nèi)的尸體忽然破棺而出搀别,到底是詐尸還是另有隱情,我是刑警寧澤尾抑,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布歇父,位于F島的核電站蒂培,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏榜苫。R本人自食惡果不足惜护戳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望垂睬。 院中可真熱鬧媳荒,春花似錦、人聲如沸羔飞。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)逻淌。三九已至么伯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間卡儒,已是汗流浹背田柔。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留骨望,地道東北人硬爆。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像擎鸠,于是被迫代替她去往敵國(guó)和親缀磕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

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