OC多線(xiàn)程學(xué)習(xí)(一) - 線(xiàn)程的相關(guān)概念

1. 進(jìn)程和線(xiàn)程的定義和關(guān)系


線(xiàn)程

  1. 線(xiàn)程是進(jìn)程的進(jìn)本執(zhí)行單元,一個(gè)進(jìn)程的所有任務(wù)都在線(xiàn)程中執(zhí)行
  2. 進(jìn)程中至少得有一個(gè)線(xiàn)程。程序啟動(dòng)后默認(rèn)開(kāi)啟一條線(xiàn)程,這條線(xiàn)程被叫做主線(xiàn)程UI線(xiàn)程

進(jìn)程

  1. 進(jìn)程指系統(tǒng)中執(zhí)行的一個(gè)應(yīng)用程序
  2. 每個(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)系可以推到出:

  1. 進(jìn)程崩潰后,不會(huì)影響其他進(jìn)程。但是線(xiàn)程崩潰后,整個(gè)進(jìn)程就崩潰了。
  2. 進(jìn)程切換時(shí),消耗資源大。所以涉及到頻繁切換時(shí),使用線(xiàn)程要優(yōu)于進(jìn)程。如果想要資源進(jìn)行并發(fā)操作時(shí),只能使用線(xiàn)程。
  3. 進(jìn)程有一個(gè)程序入口,但是線(xiàn)程不能獨(dú)立執(zhí)行,必須在進(jìn)程(應(yīng)用程序)中。
  4. 線(xiàn)程是CPU基本調(diào)度單元,進(jìn)程不是。
  5. 線(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)行、阻塞和死亡。

  1. 新建線(xiàn)程T,然后調(diào)用start,線(xiàn)程T進(jìn)入到就緒狀態(tài)。等待CPU的調(diào)度。
  2. 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)。
  3. 如果代碼中調(diào)用了Sleep方法或者鎖相關(guān)的操作,T的狀態(tài)被調(diào)整成阻塞。Sleep到時(shí)候或者獲取到同步鎖,T再回復(fù)成就緒狀態(tài),等待CPU的調(diào)度。重復(fù)步驟2
  4. 運(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

  1. 線(xiàn)程與runloop是一一對(duì)應(yīng)的。
  2. 開(kāi)啟runloop,相當(dāng)于對(duì)線(xiàn)程是一種?;?/code>處理。線(xiàn)程執(zhí)行完任務(wù)后會(huì)進(jìn)入休眠狀態(tài),有任務(wù)了就會(huì)被喚醒去執(zhí)行任務(wù)。
  3. runloop在第一次獲取時(shí)被創(chuàng)建(類(lèi)似懶加載的方式),線(xiàn)程結(jié)束時(shí)被銷(xiāo)毀。
  4. 主線(xiàn)程的runloop,是在程序啟動(dòng)后默認(rèn)創(chuàng)建好的。
  5. 子線(xiàn)程需要獲取一下(懶加載創(chuàng)建)才可以,比如在子線(xiàn)程使用定時(shí)器時(shí),如果不獲取runloop,定時(shí)器是不會(huì)發(fā)生回調(diào)的。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容