隊(duì)列和線程的關(guān)系

本文轉(zhuǎn)載至http://www.cnblogs.com/dsxniubility/p/4296937.html

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

本文是對(duì)以往學(xué)習(xí)的多線程中知識(shí)點(diǎn)的一個(gè)整理送朱。

多線程中的隊(duì)列有:串行隊(duì)列无宿,并發(fā)隊(duì)列送粱,全局隊(duì)列芬位,主隊(duì)列下梢。

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

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

提到多線程骚露,也就是四種蹬挤,pthread,NSthread棘幸,GCD焰扳,NSOperation

其中phtread是跨平臺(tái)的。GCD和NSOperation都是常用的误续,后者是基于前者的吨悍。

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

為了整體結(jié)構(gòu)更加清晰栽烂,我是用GCD來做此排列組合的實(shí)驗(yàn)躏仇。實(shí)驗(yàn)主要是通過循環(huán)內(nè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)行效果:

執(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é)果

結(jié)果顯示船响,系統(tǒng)開了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é)果

結(jié)果顯示,主線程的打印還是混在中間不確定的汗销,因?yàn)楫惒骄€程就是誰也不等誰犹褒。系統(tǒng)開了多條線程,并且執(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é)果

這個(gè)運(yùn)行結(jié)果和第1種的串行隊(duì)列叠骑,同步執(zhí)行是一模一樣的。 因?yàn)橥饺蝿?wù)的概念就是按順序執(zhí)行削茁,后面都要等宙枷。言外之意就是不允許多開線程。 同步和異步則是決定開一條還是開多條茧跋。

所以一旦是同步執(zhí)行慰丛,前面什么隊(duì)列已經(jīng)沒區(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é)果

結(jié)果顯示有點(diǎn)出人意料。主線程在睡會(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(@"我來了");

});

NSLog(@"董鉑然

come here");

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

卡死的原因是循環(huán)等待钝吮,主隊(duì)列的東西要等主線程執(zhí)行完埋涧,而因?yàn)槭峭綀?zhí)行不能開線程板辽,所以下面的任務(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é)果

結(jié)果顯示巧鸭,“用戶登陸”在主線程打印瓶您,后兩個(gè)在異步線程打印。上面的“用戶登陸”使用同步執(zhí)行纲仍,后面的扣費(fèi)和下載都是異步執(zhí)行呀袱。所以“用戶登陸”必須第一個(gè)打印出來不管等多久,然后后面的兩個(gè)異步和主線程打印會(huì)不確定順序的打印郑叠。這就是日常開發(fā)中夜赵,那些后面對(duì)其有依賴的必須要先執(zhí)行的任務(wù)使用同步執(zhí)行,然后反正都要執(zhí)行先后順序無所謂的使用異步執(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é)果

因?yàn)檎麄€(gè)block是在異步執(zhí)行的,所以即使里面“用戶登陸”是同步執(zhí)行沸版,那也無法在主線程中執(zhí)行嘁傀,只能開一條異步線程執(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é)果

全局隊(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. 開不開線程议谷,取決于執(zhí)行任務(wù)的函數(shù)炉爆,同步不開,異步開卧晓。

2. 開幾條線程芬首,取決于隊(duì)列,串行開一條逼裆,并發(fā)開多條(異步)

3. 主隊(duì)列:? 專門用來在主線程上調(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. 也可以通過判斷當(dāng)前用戶的網(wǎng)絡(luò)環(huán)境來決定開的線程數(shù)典徊。WIFI下6條杭煎,3G/4G下2~3條。

分類: Objective-C相關(guān)

標(biāo)簽: OC, iOS, 多線程, GCD, 排列組合, 主隊(duì)列, 異步線程

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末卒落,一起剝皮案震驚了整個(gè)濱河市岔帽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌导绷,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件屎飘,死亡現(xiàn)場(chǎng)離奇詭異妥曲,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)钦购,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門檐盟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人押桃,你說我怎么就攤上這事葵萎。” “怎么了唱凯?”我有些...
    開封第一講書人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵羡忘,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我磕昼,道長(zhǎng)卷雕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任票从,我火速辦了婚禮漫雕,結(jié)果婚禮上滨嘱,老公的妹妹穿的比我還像新娘。我一直安慰自己浸间,他們只是感情好太雨,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著魁蒜,像睡著了一般囊扳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上梅惯,一...
    開封第一講書人閱讀 51,182評(píng)論 1 299
  • 那天宪拥,我揣著相機(jī)與錄音,去河邊找鬼铣减。 笑死她君,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的葫哗。 我是一名探鬼主播缔刹,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼劣针!你這毒婦竟也來了校镐?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤捺典,失蹤者是張志新(化名)和其女友劉穎鸟廓,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體襟己,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡引谜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了擎浴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片员咽。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖贮预,靈堂內(nèi)的尸體忽然破棺而出贝室,到底是詐尸還是另有隱情,我是刑警寧澤仿吞,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布滑频,位于F島的核電站,受9級(jí)特大地震影響唤冈,放射性物質(zhì)發(fā)生泄漏误趴。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一务傲、第九天 我趴在偏房一處隱蔽的房頂上張望凉当。 院中可真熱鬧枣申,春花似錦、人聲如沸看杭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽楼雹。三九已至模孩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間贮缅,已是汗流浹背榨咐。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留谴供,地道東北人块茁。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像桂肌,于是被迫代替她去往敵國和親数焊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

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