iOS中的多線程

1.什么是程序, 進(jìn)程, 線程

程序: 由源代碼生成的可執(zhí)行應(yīng)用

進(jìn)程: 一個(gè)正在運(yùn)行的程序可以看做一個(gè)進(jìn)程, 進(jìn)程擁有獨(dú)立運(yùn)行所需的全部資源

進(jìn)程的作用:負(fù)責(zé)給應(yīng)用程序分配內(nèi)存空間(該空間是受保護(hù)的,獨(dú)立的)

線程: 程序中獨(dú)立運(yùn)行的代碼段

線程的作用:負(fù)責(zé)執(zhí)行應(yīng)用程序中的代碼按厘,在系統(tǒng)中運(yùn)行著的程序的代碼只能由線程執(zhí)行

線程創(chuàng)建過(guò)程:應(yīng)用程序在啟動(dòng)過(guò)程中,系統(tǒng)會(huì)自動(dòng)創(chuàng)建默認(rèn)的線程,也就是程序的主線程/UI線程

線程與進(jìn)程之間的關(guān)系:一個(gè)進(jìn)程至少有一個(gè)線程(即主線程)挖腰,一個(gè)進(jìn)程中可以有多個(gè)線程

子線程在執(zhí)行完自己的任務(wù)后會(huì)自動(dòng)銷毀


2.開(kāi)發(fā)原則

1痴怨、比較耗時(shí)的操作都放到子線程中(一般是在進(jìn)行網(wǎng)絡(luò)請(qǐng)求的時(shí)候文判,或者是執(zhí)行時(shí)間不可控的時(shí)候)

2、UI操作橡庞、與用戶交互的代碼都放到主線程中,其一是因?yàn)闉榱吮WC用戶操作的流程性印蔗,其二是因?yàn)樗械腢I控件都在UIKIT框架中扒最,而UIKIT框架采用的就是這種機(jī)制,蘋果公司也推薦這種用法华嘹,都是非線程安全的吧趣,為了保證正確,將所有的用戶交互的代碼放到主線程中耙厚,而單一的線程是按順序執(zhí)行的强挫,所以就避免了非線程安全的問(wèn)題


3.線程內(nèi)的代碼的執(zhí)行順序:

串行執(zhí)行:同一線程中,該線程中的任務(wù)代碼按順序執(zhí)行薛躬,同一時(shí)間只能執(zhí)行一塊代碼

并發(fā)執(zhí)行:一個(gè)進(jìn)程可以創(chuàng)建多個(gè)子線程俯渤,在不同的線程中,任務(wù)同時(shí)執(zhí)行(其實(shí)是一種假象泛豪,是因?yàn)镃PU的調(diào)度速度非吵砘澹快速,所以感覺(jué)是一起執(zhí)行的)(即多線程)

并行執(zhí)行:真正的同時(shí)執(zhí)行诡曙,由多個(gè)CPU同時(shí)執(zhí)行


4.多線程的優(yōu)點(diǎn)

a臀叙、能適當(dāng)提高程序的執(zhí)行效率

b、能適當(dāng)提高資源利用率(CPU价卤、內(nèi)存利用率)


5.多線程的缺點(diǎn)

a劝萤、開(kāi)啟線程需要占用一定的內(nèi)存空間(默認(rèn)情況下,主線程占用1M慎璧,子線程占用512KB)床嫌,如果開(kāi)啟大量的線程,會(huì)占用大量的內(nèi)存空間胸私,降低程序的性能

b厌处、線程越多,CPU在調(diào)度線程上的開(kāi)銷就越大

c'程序設(shè)計(jì)更加復(fù)雜:比如線程之間的通信岁疼、多線程的數(shù)據(jù)共享


6.線程安全問(wèn)題

線程安全:保證多條線程進(jìn)行讀寫操作,都能夠得到正確的結(jié)果!

使用線程同步技術(shù)

解決方案:互斥鎖

優(yōu)點(diǎn):能有效防止因多線程搶奪資源而引起的數(shù)據(jù)安全問(wèn)題!

缺點(diǎn):需要消耗大量的CPU資源!

原理:多條線程在同一條線上按順序執(zhí)行任務(wù)!



GCD

Grand Central Dispatch阔涉,聽(tīng)名字就霸氣。它是蘋果為多核的并行運(yùn)算提出的解決方案,所以會(huì)自動(dòng)合理地利用更多的CPU內(nèi)核(比如雙核瑰排、四核)贯要,最重要的是它會(huì)自動(dòng)管理線程的生命周期(創(chuàng)建線程、調(diào)度任務(wù)椭住、銷毀線程)崇渗,完全不需要我們管理,我們只需要告訴干什么就行京郑。同時(shí)它使用的也是c語(yǔ)言宅广,不過(guò)由于使用了 Block(Swift里叫做閉包),使得使用起來(lái)更加方便傻挂,而且靈活乘碑。所以基本上大家都使用GCD這套方案,老少咸宜金拒,實(shí)在是居家旅行兽肤、殺人滅口,必備良藥绪抛。不好意思资铡,有點(diǎn)中二,咱們繼續(xù)幢码。

任務(wù)和隊(duì)列

在GCD中笤休,加入了兩個(gè)非常重要的概念:任務(wù)隊(duì)列

任務(wù):即操作症副,你想要干什么店雅,說(shuō)白了就是一段代碼,在 GCD 中就是一個(gè) Block贞铣,所以添加任務(wù)十分方便闹啦。任務(wù)有兩種執(zhí)行方式:同步執(zhí)行異步執(zhí)行,他們之間的區(qū)別是是否會(huì)創(chuàng)建新的線程辕坝。

這里說(shuō)的并不準(zhǔn)確窍奋,同步(sync)和異步(async)的主要區(qū)別在于會(huì)不會(huì)阻塞當(dāng)前線程,直到Block中的任務(wù)執(zhí)行完畢酱畅!

如果是同步(sync)操作琳袄,它會(huì)阻塞當(dāng)前線程并等待Block中的任務(wù)執(zhí)行完畢,然后當(dāng)前線程才會(huì)繼續(xù)往下運(yùn)行纺酸。

如果是異步(async)操作窖逗,當(dāng)前線程會(huì)直接往下執(zhí)行,它不會(huì)阻塞當(dāng)前線程餐蔬。

隊(duì)列:用于存放任務(wù)滑负。一共有兩種隊(duì)列在张,串行隊(duì)列并行隊(duì)列

串行隊(duì)列中的任務(wù)會(huì)根據(jù)隊(duì)列的定義 FIFO 的執(zhí)行矮慕,一個(gè)接一個(gè)的先進(jìn)先出的進(jìn)行執(zhí)行。

更新:放到串行隊(duì)列的任務(wù)啄骇,GCD 會(huì)FIFO(先進(jìn)先出)地取出來(lái)一個(gè)痴鳄,執(zhí)行一個(gè),然后取下一個(gè)缸夹,這樣一個(gè)一個(gè)的執(zhí)行痪寻。

并行隊(duì)列中的任務(wù)根據(jù)同步或異步有不同的執(zhí)行方式。

更新:放到并行隊(duì)列的任務(wù)虽惭,GCD 也會(huì)FIFO的取出來(lái)橡类,但不同的是,它取出來(lái)一個(gè)就會(huì)放到別的線程芽唇,然后再取出來(lái)一個(gè)又放到另一個(gè)的線程顾画。這樣由于取的動(dòng)作很快,忽略不計(jì)匆笤,看起來(lái)研侣,所有的任務(wù)都是一起執(zhí)行的。不過(guò)需要注意炮捧,GCD 會(huì)根據(jù)系統(tǒng)資源控制并行的數(shù)量庶诡,所以如果任務(wù)很多,它并不會(huì)讓所有任務(wù)同時(shí)執(zhí)行咆课。

雖然很繞末誓,但請(qǐng)看下表:

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

串行隊(duì)列當(dāng)前線程,一個(gè)一個(gè)執(zhí)行其他線程书蚪,一個(gè)一個(gè)執(zhí)行

并行隊(duì)列當(dāng)前線程喇澡,一個(gè)一個(gè)執(zhí)行開(kāi)很多線程,一起執(zhí)行

創(chuàng)建隊(duì)列

主隊(duì)列:這是一個(gè)特殊的串行隊(duì)列善炫。什么是主隊(duì)列撩幽,大家都知道吧,它用于刷新 UI箩艺,任何需要刷新 UI 的工作都要在主隊(duì)列執(zhí)行窜醉,所以一般耗時(shí)的任務(wù)都要放到別的線程執(zhí)行。

//OBJECTIVE-Cdispatch_queue_tqueue= ispatch_get_main_queue();//SWIFTletqueue= ispatch_get_main_queue()

自己創(chuàng)建的隊(duì)列凡是自己創(chuàng)建的隊(duì)列都是串行隊(duì)列艺谆。其中第一個(gè)參數(shù)是標(biāo)識(shí)符榨惰,用于 DEBUG 的時(shí)候標(biāo)識(shí)唯一的隊(duì)列,可以為空静汤。大家可以看xcode的文檔查看參數(shù)意義琅催。

更新:自己可以創(chuàng)建串行隊(duì)列, 也可以創(chuàng)建并行隊(duì)列居凶。看下面的代碼(代碼已更新)藤抡,它有兩個(gè)參數(shù)侠碧,第一個(gè)上面已經(jīng)說(shuō)了,第二個(gè)才是最重要的缠黍。

第二個(gè)參數(shù)用來(lái)表示創(chuàng)建的隊(duì)列是串行的還是并行的弄兜,傳入DISPATCH_QUEUE_SERIAL或NULL表示創(chuàng)建串行隊(duì)列。傳入DISPATCH_QUEUE_CONCURRENT表示創(chuàng)建并行隊(duì)列瓷式。

//OBJECTIVE-C//串行隊(duì)列dispatch_queue_tqueue= dispatch_queue_create("tk.bourne.testQueue",NULL);dispatch_queue_tqueue= dispatch_queue_create("tk.bourne.testQueue", DISPATCH_QUEUE_SERIAL);//并行隊(duì)列dispatch_queue_tqueue= dispatch_queue_create("tk.bourne.testQueue", DISPATCH_QUEUE_CONCURRENT);//SWIFT//串行隊(duì)列l(wèi)etqueue= dispatch_queue_create("tk.bourne.testQueue", nil);? letqueue= dispatch_queue_create("tk.bourne.testQueue", DISPATCH_QUEUE_SERIAL)//并行隊(duì)列l(wèi)etqueue= dispatch_queue_create("tk.bourne.testQueue", DISPATCH_QUEUE_CONCURRENT)

全局并行隊(duì)列這應(yīng)該是唯一一個(gè)并行隊(duì)列替饿,只要是并行任務(wù)一般都加入到這個(gè)隊(duì)列。這是系統(tǒng)提供的一個(gè)并發(fā)隊(duì)列贸典。

//OBJECTIVE-Cdispatch_queue_tqueue= dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);//SWIFTletqueue= dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)





創(chuàng)建多線程的多種方法

方法一:

NSThread *t = [[NSThread alloc] initWithTarget:self selector:@selector(mutableThread) object:nil];

方法二:

[NSThread detachNewThreadSelector:@selector(mutableThread) toTarget:self withObject:nil];

方法三:

[self performSelectorInBackground:@selector(mutableThread) withObject:nil];

方法四:多線程blog創(chuàng)建

NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];

//會(huì)開(kāi)啟一個(gè)多線程

[operationQueue addOperationWithBlock:^{

for(int i = 0; i < 50 ;i++)

{

NSLog(@"多線程:%d",i);

}

}];

方法五:

//相當(dāng)于是一個(gè)線程池

NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];

operationQueue.maxConcurrentOperationCount = 1;//設(shè)置并發(fā)數(shù)

//創(chuàng)建線程

NSInvocationOperation *opertion1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(thread1) object:nil];

//設(shè)置線程的優(yōu)先級(jí)

[opertion1 setQueuePriority:NSOperationQueuePriorityVeryLow];

//創(chuàng)建另一個(gè)線程

NSInvocationOperation *opertion2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(thread2) object:nil];

[opertion2 setQueuePriority:NSOperationQueuePriorityHigh];

方法六:

dispatch_queue_t queue = dispatch_queue_create("test",NULL);

dispatch_async(queue,^{

for(int i=0;i<50;i++)

{

NSLog(@"多線程:%d",i);

});





最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末视卢,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子廊驼,更是在濱河造成了極大的恐慌据过,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,865評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蔬充,死亡現(xiàn)場(chǎng)離奇詭異蝶俱,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)饥漫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門榨呆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人庸队,你說(shuō)我怎么就攤上這事积蜻。” “怎么了彻消?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,631評(píng)論 0 364
  • 文/不壞的土叔 我叫張陵竿拆,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我宾尚,道長(zhǎng)丙笋,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,199評(píng)論 1 300
  • 正文 為了忘掉前任煌贴,我火速辦了婚禮御板,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘牛郑。我一直安慰自己怠肋,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,196評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布淹朋。 她就那樣靜靜地躺著笙各,像睡著了一般钉答。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上杈抢,一...
    開(kāi)封第一講書(shū)人閱讀 52,793評(píng)論 1 314
  • 那天数尿,我揣著相機(jī)與錄音,去河邊找鬼惶楼。 笑死砌创,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的鲫懒。 我是一名探鬼主播,決...
    沈念sama閱讀 41,221評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼刽辙,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼窥岩!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起宰缤,我...
    開(kāi)封第一講書(shū)人閱讀 40,174評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤颂翼,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后慨灭,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體朦乏,經(jīng)...
    沈念sama閱讀 46,699評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,770評(píng)論 3 343
  • 正文 我和宋清朗相戀三年氧骤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了呻疹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,918評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡筹陵,死狀恐怖刽锤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情朦佩,我是刑警寧澤并思,帶...
    沈念sama閱讀 36,573評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站语稠,受9級(jí)特大地震影響宋彼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜仙畦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,255評(píng)論 3 336
  • 文/蒙蒙 一输涕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧议泵,春花似錦占贫、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,749評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)瞳收。三九已至薪缆,卻和暖如春膜蛔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背他挎。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,862評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工烫葬, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留界弧,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,364評(píng)論 3 379
  • 正文 我出身青樓搭综,卻偏偏與公主長(zhǎng)得像垢箕,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子兑巾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,926評(píng)論 2 361

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