隊(duì)列和線程

[iOS多線程中用僧,隊(duì)列和執(zhí)行的排列組合結(jié)果分析]

多線程中的隊(duì)列有:串行隊(duì)列,并發(fā)隊(duì)列辰如,全局隊(duì)列普监,主隊(duì)列

執(zhí)行的方法有:同步執(zhí)行和異步執(zhí)行丧没。那么兩兩一組合會(huì)有哪些注意事項(xiàng)呢鹰椒?

提到多線程,也就是四種呕童,pthread漆际,NSthread,GCD夺饲,NSOperation

其中phtread是跨平臺(tái)的奸汇。GCD和NSOperation都是常用的,后者是基于前者的往声。

但是兩者區(qū)別:GCD的核心概念是將一個(gè)任務(wù)添加到隊(duì)列擂找,指定任務(wù)執(zhí)行的方法,然后執(zhí)行浩销。 NSOperation則是直接將一個(gè)操作添加到隊(duì)列中贯涎。

為了整體結(jié)構(gòu)更加清晰,我是用GCD來(lái)做此排列組合的實(shí)驗(yàn)慢洋。實(shí)驗(yàn)主要是通過(guò)循環(huán)內(nèi)打印和主線程的打印先后順序來(lái)判斷結(jié)果塘雳,最后再加以總結(jié)

1.串行隊(duì)列,同步執(zhí)行

dispatch_queue_t q = dispatch_queue_create("dantesx", NULL);
 
// 執(zhí)行任務(wù)
for (int i = 0; i<10; i++) {
    dispatch_sync(q, ^{
        NSLog(@"%@ %d", [NSThread currentThread], i);
    });
}
 
NSLog(@"董鉑然 come here");

運(yùn)行效果:


211237257056952.png

執(zhí)行結(jié)果可以清楚的看到全在主線程執(zhí)行普筹,并且是按照數(shù)序執(zhí)行败明,循環(huán)結(jié)束之后主線程的打印才輸出。

2.串行隊(duì)列太防,異步執(zhí)行

dispatch_queue_t q = dispatch_queue_create("dantesx", NULL);
 
for (int i = 0; i<10; i++) {
    dispatch_async(q, ^{
        NSLog(@"%@ %d", [NSThread currentThread], i);
    });
}
//    [NSThread sleepForTimeInterval:0.001];
NSLog(@"董鉑然 come here");

運(yùn)行結(jié)果


211247365178513.png

結(jié)果顯示妻顶,系統(tǒng)開(kāi)了1條異步線程,因此全部在線程2執(zhí)行,并且是順序執(zhí)行讳嘱。主線程打印雖然在最上面幔嗦,但是這個(gè)先后順序是不確定,如果睡個(gè)0.001秒沥潭,主線程的打印會(huì)混在中間崭添。

3.并發(fā)隊(duì)列,異步執(zhí)行

// 1. 隊(duì)列
dispatch_queue_t q = dispatch_queue_create("dantesx", DISPATCH_QUEUE_CONCURRENT);
 
// 2. 異步執(zhí)行
for (int i = 0; i<10; i++) {
    dispatch_async(q, ^{
        NSLog(@"%@ %d", [NSThread currentThread], i);
    });
}
//    [NSThread sleepForTimeInterval:2.0];
NSLog(@"董鉑然 come here");

運(yùn)行結(jié)果

211252300801494.png

結(jié)果顯示叛氨,主線程的打印還是混在中間不確定的,因?yàn)楫惒骄€程就是誰(shuí)也不等誰(shuí)棘伴。系統(tǒng)開(kāi)了多條線程寞埠,并且執(zhí)行的順序也是亂序的

4.并發(fā)隊(duì)列,同步執(zhí)行

// 1. 隊(duì)列
dispatch_queue_t q = dispatch_queue_create("dantesx", DISPATCH_QUEUE_CONCURRENT);
 
// 2. 同步執(zhí)行
for (int i = 0; i<10; i++) {
    dispatch_sync(q, ^{
        NSLog(@"%@ %d", [NSThread currentThread], i);
    });
}
//    [NSThread sleepForTimeInterval:2.0];
NSLog(@"董鉑然 come here");

運(yùn)行結(jié)果

211254312524376.png

這個(gè)運(yùn)行結(jié)果和第1種的串行隊(duì)列焊夸,同步執(zhí)行是一模一樣的仁连。 因?yàn)橥饺蝿?wù)的概念就是按順序執(zhí)行,后面都要等阱穗。言外之意就是不允許多開(kāi)線程饭冬。 同步和異步則是決定開(kāi)一條還是開(kāi)多條。

所以一旦是同步執(zhí)行揪阶,前面什么隊(duì)列已經(jīng)沒(méi)區(qū)別了昌抠。

5.主隊(duì)列,異步執(zhí)行

// 1. 主隊(duì)列 - 程序啟動(dòng)之后已經(jīng)存在主線程鲁僚,主隊(duì)列同樣存在
dispatch_queue_t q = dispatch_get_main_queue();
// 2. 安排一個(gè)任務(wù)
for (int i = 0; i<10; i++) {
    dispatch_async(q, ^{
        NSLog(@"%@ %d", [NSThread currentThread], i);
    });
}
NSLog(@"睡會(huì)");
[NSThread sleepForTimeInterval:2.0];
NSLog(@"董鉑然 come here");

運(yùn)行結(jié)果

220005483771521.png

結(jié)果顯示有點(diǎn)出人意料炊苫。異步主隊(duì)列是不會(huì)開(kāi)啟新線程。主線程在睡會(huì)之后才打印冰沙,循環(huán)一直在等著侨艾。因?yàn)橹麝?duì)列的任務(wù)雖然會(huì)加到主線程中執(zhí)行,但是如果主線程里也有任務(wù)就必須等主線程任務(wù)執(zhí)行完才輪到主隊(duì)列的拓挥。

6.主隊(duì)列唠梨,同步執(zhí)行

dispatch_queue_t q = dispatch_get_main_queue();
 
NSLog(@"卡死了嗎?");
 
dispatch_sync(q, ^{
    NSLog(@"我來(lái)了");
});
 
NSLog(@"董鉑然 come here");

運(yùn)行結(jié)果為卡死

卡死的原因是循環(huán)等待侥啤,主隊(duì)列的東西要等主線程執(zhí)行完当叭,而因?yàn)槭峭綀?zhí)行不能開(kāi)線程,所以下面的任務(wù)要等上面的任務(wù)執(zhí)行完愿棋,所以卡死科展。這是排列組合中唯一一個(gè)會(huì)卡死的組合。

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

dispatch_queue_t q = dispatch_queue_create("dantesx", DISPATCH_QUEUE_CONCURRENT);
// 1. 用戶登錄糠雨,必須要第一個(gè)執(zhí)行
dispatch_sync(q, ^{
    [NSThread sleepForTimeInterval:2.0];
    NSLog(@"用戶登錄 %@", [NSThread currentThread]);
});
// 2. 扣費(fèi)
dispatch_async(q, ^{
    NSLog(@"扣費(fèi) %@", [NSThread currentThread]);
});
// 3. 下載
dispatch_async(q, ^{
    NSLog(@"下載 %@", [NSThread currentThread]);
});
NSLog(@"董鉑然 come here");

運(yùn)行結(jié)果

220013207056898.png

結(jié)果顯示才睹,“用戶登陸”在主線程打印,后兩個(gè)在異步線程打印。上面的“用戶登陸”使用同步執(zhí)行琅攘,后面的扣費(fèi)和下載都是異步執(zhí)行垮庐。所以“用戶登陸”必須第一個(gè)打印出來(lái)不管等多久,然后后面的兩個(gè)異步和主線程打印會(huì)不確定順序的打印坞琴。這就是日常開(kāi)發(fā)中哨查,那些后面對(duì)其有依賴的必須要先執(zhí)行的任務(wù)使用同步執(zhí)行,然后反正都要執(zhí)行先后順序無(wú)所謂的使用異步執(zhí)行剧辐。

8.block異步任務(wù)包裹同步任務(wù)

dispatch_queue_t q = dispatch_queue_create("dantesx", DISPATCH_QUEUE_CONCURRENT);
void (^task)() = ^ {
    // 1. 用戶登錄寒亥,必須要第一個(gè)執(zhí)行
    dispatch_sync(q, ^{
        NSLog(@"用戶登錄 %@", [NSThread currentThread]);
    });
    // 2. 扣費(fèi)
    dispatch_async(q, ^{
        NSLog(@"扣費(fèi) %@", [NSThread currentThread]);
    });
    // 3. 下載
    dispatch_async(q, ^{
         
        NSLog(@"下載 %@", [NSThread currentThread]);
    });
};
 
dispatch_async(q, task);
[NSThread sleepForTimeInterval:1.0];
NSLog(@"董鉑然 come here");

運(yùn)行結(jié)果

截屏2021-02-25 上午12.44.06.png

因?yàn)檎麄€(gè)block是在異步執(zhí)行的,所以即使里面“用戶登陸”是同步執(zhí)行荧关,那也無(wú)法在主線程中執(zhí)行溉奕,只能開(kāi)新的線程執(zhí)行(這里可能是多條),因?yàn)槭峭降乃员仨毜人葓?zhí)行忍啤,后面的“扣費(fèi)”和“下載”在上面同步執(zhí)行結(jié)束之后加勤,不確定順序的打印。

9.全局隊(duì)列

dispatch_queue_t q = dispatch_get_global_queue(0, 0);
 
for (int i = 0; i < 10; i++) {
    dispatch_async(q, ^{
        NSLog(@"%@ %d", [NSThread currentThread], i);
    });
}
[NSThread sleepForTimeInterval:1.0];
NSLog(@"com here");

運(yùn)行結(jié)果

截屏2021-02-25 上午12.42.20.png

全局隊(duì)列的本質(zhì)就是并發(fā)隊(duì)列同波,只是在后面加入了鳄梅,“服務(wù)質(zhì)量”,和“調(diào)度優(yōu)先級(jí)” 兩個(gè)參數(shù)未檩,這兩個(gè)參數(shù)一般為了系統(tǒng)間的適配戴尸,最好直接填0和0。

如果不是在董鉑然博客園看到這邊文章請(qǐng) 點(diǎn)擊查看原文

總結(jié):

1. 開(kāi)不開(kāi)線程讹挎,取決于執(zhí)行任務(wù)的函數(shù)校赤,同步不開(kāi),異步開(kāi)筒溃。

2. 開(kāi)幾條線程马篮,取決于隊(duì)列,串行開(kāi)一條怜奖,并發(fā)開(kāi)多條(異步)

3. 主隊(duì)列: 專門用來(lái)在主線程上調(diào)度任務(wù)的"隊(duì)列"浑测,主隊(duì)列不能在其他線程中調(diào)度任務(wù)!

4. 如果主線程上當(dāng)前正在有執(zhí)行的任務(wù)歪玲,主隊(duì)列暫時(shí)不會(huì)調(diào)度任務(wù)的執(zhí)行迁央!主隊(duì)列同步任務(wù),會(huì)造成死鎖滥崩。原因是循環(huán)等待

5. 同步任務(wù)可以隊(duì)列調(diào)度多個(gè)異步任務(wù)前岖圈,指定一個(gè)同步任務(wù),讓所有的異步任務(wù)钙皮,等待同步任務(wù)執(zhí)行完成蜂科,這是依賴關(guān)系顽决。

6. 全局隊(duì)列:并發(fā),能夠調(diào)度多個(gè)線程导匣,執(zhí)行效率高才菠,但是相對(duì)費(fèi)電。 串行隊(duì)列效率較低贡定,省電省流量赋访,或者是任務(wù)之間需要依賴也可以使用串行隊(duì)列。

7. 也可以通過(guò)判斷當(dāng)前用戶的網(wǎng)絡(luò)環(huán)境來(lái)決定開(kāi)的線程數(shù)缓待。WIFI下6條蚓耽,3G/4G下2~3條。

本文轉(zhuǎn)載董鉑然博客園看到這邊文章請(qǐng) 點(diǎn)擊查看原文

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末旋炒,一起剝皮案震驚了整個(gè)濱河市田晚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌国葬,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件芹壕,死亡現(xiàn)場(chǎng)離奇詭異汇四,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)踢涌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門通孽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人睁壁,你說(shuō)我怎么就攤上這事背苦。” “怎么了潘明?”我有些...
    開(kāi)封第一講書人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵行剂,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我钳降,道長(zhǎng)厚宰,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任遂填,我火速辦了婚禮铲觉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘吓坚。我一直安慰自己撵幽,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布礁击。 她就那樣靜靜地躺著盐杂,像睡著了一般逗载。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上况褪,一...
    開(kāi)封第一講書人閱讀 49,816評(píng)論 1 290
  • 那天撕贞,我揣著相機(jī)與錄音,去河邊找鬼测垛。 笑死捏膨,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的食侮。 我是一名探鬼主播号涯,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼锯七!你這毒婦竟也來(lái)了链快?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤眉尸,失蹤者是張志新(化名)和其女友劉穎域蜗,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體噪猾,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡霉祸,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了袱蜡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丝蹭。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖坪蚁,靈堂內(nèi)的尸體忽然破棺而出奔穿,到底是詐尸還是另有隱情,我是刑警寧澤敏晤,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布贱田,位于F島的核電站,受9級(jí)特大地震影響嘴脾,放射性物質(zhì)發(fā)生泄漏湘换。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一统阿、第九天 我趴在偏房一處隱蔽的房頂上張望彩倚。 院中可真熱鬧,春花似錦扶平、人聲如沸帆离。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)哥谷。三九已至岸夯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間们妥,已是汗流浹背猜扮。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留监婶,地道東北人旅赢。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像惑惶,于是被迫代替她去往敵國(guó)和親煮盼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348

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