1. 進(jìn)程和線(xiàn)程的定義和關(guān)系
線(xiàn)程
- 線(xiàn)程是進(jìn)程的進(jìn)本執(zhí)行單元,一個(gè)進(jìn)程的所有任務(wù)都在線(xiàn)程中執(zhí)行
- 進(jìn)程中至少得有一個(gè)線(xiàn)程。程序啟動(dòng)后默認(rèn)開(kāi)啟一條線(xiàn)程,這條線(xiàn)程被叫做
主線(xiàn)程或UI線(xiàn)程
進(jìn)程
- 進(jìn)程指系統(tǒng)中執(zhí)行的一個(gè)應(yīng)用程序
- 每個(gè)進(jìn)程之間是獨(dú)立的,并且進(jìn)程運(yùn)行在專(zhuān)用的且受保護(hù)的內(nèi)存空間中
Mac系統(tǒng)中活動(dòng)監(jiān)視器
通過(guò)Mac系統(tǒng)中的“活動(dòng)監(jiān)視器”能夠看到系統(tǒng)中開(kāi)啟的進(jìn)程

- 圖中展示了當(dāng)前系統(tǒng)中開(kāi)啟的
進(jìn)程和進(jìn)程中開(kāi)啟的線(xiàn)程數(shù) - 有icon的說(shuō)明有用戶(hù)界面;沒(méi)有icon是沒(méi)有用戶(hù)界面;
進(jìn)程和線(xiàn)程的關(guān)系
- 進(jìn)程中的線(xiàn)程共享本進(jìn)程中的地址空間。進(jìn)程之間是互相獨(dú)立的地址空間
- 進(jìn)程中的線(xiàn)程共享本進(jìn)程中的資源,如內(nèi)存、I/O、CPU等。進(jìn)程之間是資源獨(dú)立的。
通過(guò)以上的關(guān)系可以推到出:
- 進(jìn)程崩潰后,不會(huì)影響其他進(jìn)程。但是線(xiàn)程崩潰后,整個(gè)進(jìn)程就崩潰了。
- 進(jìn)程切換時(shí),消耗資源大。所以涉及到頻繁切換時(shí),使用線(xiàn)程要優(yōu)于進(jìn)程。如果想要資源進(jìn)行并發(fā)操作時(shí),只能使用線(xiàn)程。
- 進(jìn)程有一個(gè)程序入口,但是線(xiàn)程不能獨(dú)立執(zhí)行,必須在進(jìn)程(應(yīng)用程序)中。
- 線(xiàn)程是CPU基本調(diào)度單元,進(jìn)程不是。
- 線(xiàn)程沒(méi)有地址空間,線(xiàn)程是包含在進(jìn)程的地址空間中。
2. 多線(xiàn)程
優(yōu)點(diǎn)
- 能適當(dāng)提?程序的執(zhí)?效率
- 能適當(dāng)提?資源的利?率(CPU,內(nèi)存)
- 線(xiàn)程上的任務(wù)執(zhí)?完成后,線(xiàn)程會(huì)?動(dòng)銷(xiāo)毀
缺點(diǎn)
- 開(kāi)啟線(xiàn)程需要占??定的內(nèi)存空間(默認(rèn)情況下,每?個(gè)線(xiàn)程都占 512 KB)
- 如果開(kāi)啟?量的線(xiàn)程,會(huì)占??量的內(nèi)存空間,降低程序的性能
- 線(xiàn)程越多,CPU 在調(diào)?線(xiàn)程上的開(kāi)銷(xiāo)就越?
- 程序設(shè)計(jì)更加復(fù)雜,?如線(xiàn)程間的通信、多線(xiàn)程的數(shù)據(jù)共享
多線(xiàn)程技術(shù)方案
- pthread:一套通用的多線(xiàn)程API,適用于Unix、Linux、Windows等操作系統(tǒng)。使用C語(yǔ)言,需要開(kāi)發(fā)人員管理線(xiàn)程的生命周期。
- NSThread:更加面向?qū)ο?,使用OC語(yǔ)言,也是需要開(kāi)發(fā)人員管理線(xiàn)程的生命周期。
- GCD:蘋(píng)果提供的替代NSThread的方案,使用C語(yǔ)言實(shí)現(xiàn),不需要開(kāi)發(fā)人員管理線(xiàn)程生命周期。
- NSOperation:基于GCD,使用上更加面向?qū)ο?。語(yǔ)言是OC,同樣不需要開(kāi)發(fā)人員管理線(xiàn)程聲明周期。
擴(kuò)展 - C與OC橋接相關(guān)
- __bridge: 只做類(lèi)型轉(zhuǎn)換,但是不修改對(duì)象內(nèi)存的管理權(quán)。
- __bridge_retained:也可以使用CFBridgingRetain,將OC對(duì)象轉(zhuǎn)換為Core Foundation對(duì)象,同時(shí)將對(duì)象內(nèi)存的管理權(quán)交給開(kāi)發(fā)人員,需要使用CFRelease或者相關(guān)方法進(jìn)行釋放。
- __bridge_transfer:也可以使用CFBridgingRelease,將Core Foundation對(duì)象轉(zhuǎn)換為OC對(duì)象,并將對(duì)象內(nèi)存的管理權(quán)交給ARC。
3. 線(xiàn)程的生命周期
線(xiàn)程的生命周期中有的幾種狀態(tài):就緒、運(yùn)行、阻塞和死亡。

- 新建線(xiàn)程T,然后調(diào)用
start,線(xiàn)程T進(jìn)入到就緒狀態(tài)。等待CPU的調(diào)度。 - CPU調(diào)度線(xiàn)程池中可調(diào)用的線(xiàn)程,如果調(diào)用T,此時(shí)T是運(yùn)行狀態(tài)。如果調(diào)用了其他線(xiàn)程,那么T繼續(xù)保持就緒狀態(tài)。
- 如果代碼中調(diào)用了
Sleep方法或者鎖相關(guān)的操作,T的狀態(tài)被調(diào)整成阻塞。Sleep到時(shí)候或者獲取到同步鎖,T再回復(fù)成就緒狀態(tài),等待CPU的調(diào)度。重復(fù)步驟2 - 運(yùn)行完美結(jié)束后,線(xiàn)程死亡。
線(xiàn)程池
線(xiàn)程池就是線(xiàn)程的集合容器。容器里管理著線(xiàn)程的創(chuàng)建、回收和重復(fù)利用線(xiàn)程。
使用線(xiàn)程池優(yōu)點(diǎn):通過(guò)線(xiàn)程池,可以做到對(duì)線(xiàn)程的管理,比如重復(fù)利用已經(jīng)創(chuàng)建出來(lái)的線(xiàn)程,降低創(chuàng)建和銷(xiāo)毀線(xiàn)程時(shí)對(duì)性能的消耗。
大致的流程圖如下:

- 大致進(jìn)行了三個(gè)條件判斷:
- 條件1:判斷線(xiàn)程數(shù)量
- 條件2:判斷任務(wù)隊(duì)列
- 條件3:判斷是否有閑著的線(xiàn)程
- 先判斷條件1,線(xiàn)程池中的線(xiàn)程數(shù)是否小于核心線(xiàn)程數(shù),不小于直接創(chuàng)建線(xiàn)程去執(zhí)行任務(wù)
- 如果條件1不滿(mǎn)足,條件2是去判斷任務(wù)隊(duì)列的狀況,如果任務(wù)隊(duì)列沒(méi)滿(mǎn)就將任務(wù)加入到隊(duì)列中,等待線(xiàn)程去執(zhí)行。
- 條件3如果有閑著線(xiàn)程,直接安排該線(xiàn)程去執(zhí)行任務(wù)
- 如果以上都不滿(mǎn)足,就要進(jìn)行飽和策略的處理了。
飽和策略
- AbortPolicy 直接拋出RejectedExecutionExeception異常來(lái)阻?系統(tǒng)正常運(yùn)?。
- CallerRunsPolicy 將任務(wù)回退到調(diào)?者
- DisOldestPolicy 丟掉等待最久的任務(wù)
- DisCardPolicy 直接丟棄任務(wù)
這四點(diǎn)可以聯(lián)想一下工作中的場(chǎng)景,如果當(dāng)前非常的忙,已經(jīng)是滿(mǎn)負(fù)荷的工作狀態(tài),此時(shí)有一個(gè)新需求下來(lái)需要你做,那么:
- AbortPolicy:整個(gè)人的心態(tài)崩了,沒(méi)法繼續(xù)工作。
- CallerRunsPolicy:把需求推回給發(fā)起者,并告訴他,現(xiàn)在沒(méi)有時(shí)間,等有時(shí)間再去做。
- DisOldestPolicy:做這個(gè)需求就得丟掉已經(jīng)排好的需求表中優(yōu)先級(jí)最低的任務(wù),這樣才能按時(shí)完成全部工作。
- DisCardPolicy:直接說(shuō)這個(gè)需求做不了。
4. 線(xiàn)程與runloop
- 線(xiàn)程與runloop是一一對(duì)應(yīng)的。
- 開(kāi)啟runloop,相當(dāng)于對(duì)線(xiàn)程是一種
?;?/code>處理。線(xiàn)程執(zhí)行完任務(wù)后會(huì)進(jìn)入休眠狀態(tài),有任務(wù)了就會(huì)被喚醒去執(zhí)行任務(wù)。 - runloop在第一次獲取時(shí)被創(chuàng)建(類(lèi)似懶加載的方式),線(xiàn)程結(jié)束時(shí)被銷(xiāo)毀。
- 主線(xiàn)程的runloop,是在程序啟動(dòng)后默認(rèn)創(chuàng)建好的。
- 子線(xiàn)程需要獲取一下(懶加載創(chuàng)建)才可以,比如在子線(xiàn)程使用定時(shí)器時(shí),如果不獲取runloop,定時(shí)器是不會(huì)發(fā)生回調(diào)的。