多線程
1意荤、線程的定義
- 線程是進程的基本執(zhí)行單元辩尊,一個進程的所有任務都在線程中執(zhí)行
- 進程要想執(zhí)行任務,必須得有線程说庭,進程至少要有一條線程
- 程序啟動會默認開啟一條線程荐吉,這條線程被稱為主線程或 UI 線程
2、進程的定義
- 進程是指在系統(tǒng)中正在運行的一個應用程序
- 每個進程之間是獨立的口渔,每個進程均運行在其專用的且受保護的內(nèi)存
3样屠、進程與線程的關系
- 地址空間:同一進程的線程共享本進程的地址空間,而進程之間則是獨立的地址空間缺脉。
- 資源擁有:同一進程內(nèi)的線程共享本進程的資源如內(nèi)存痪欲、I/O、cpu等攻礼,但是進程之間的資源是獨立的业踢。
- 一個進程崩潰后,在保護模式下不會對其他進程產(chǎn)生影響礁扮,但是一個線程崩潰整個進程都死掉知举。所以多進程要比多線程健壯。
- 進程切換時太伊,消耗的資源大雇锡,效率高。所以涉及到頻繁的切換時僚焦,使用線程要好于進程锰提。同樣如果要求同時進行并且又要共享某些變量的并發(fā)操作,只能用線程不能用進程
- 執(zhí)行過程:每個獨立的進程有一個程序運行的入口芳悲、順序執(zhí)行序列和程序入口立肘。但是線程不能獨立執(zhí)行,必須依存在應用程序中名扛,由應用程序提供多個線程執(zhí)行控制谅年。
- 線程是處理器調(diào)度的基本單位,但是進程不是肮韧。
4融蹂、多線程的意義
- 優(yōu)點
- 能適當提高程序的執(zhí)行效率
- 能適當提高資源的利用率(CPU旺订,內(nèi)存)
- 線程上的任務執(zhí)行完成后,線程會自動銷毀
- 缺點
- 開啟線程需要占用一定的內(nèi)存空間(默認情況下殿较,每一個線程都占 512 KB)
- 如果開啟大量的線程耸峭,會占用大量的內(nèi)存空間,降低程序的性能
- 線程越多淋纲,CPU 在調(diào)用線程上的開銷就越大
- 程序設計更加復雜劳闹,比如線程間的通信、多線程的數(shù)據(jù)共享
5洽瞬、多線程的原理
cpu在單位時間片里快速在各個線程之間切換本涕。實現(xiàn)假象的同時執(zhí)行。
image.png
6伙窃、多線程在iOS中實現(xiàn)的技術方案
image.png
7菩颖、多線程的生命周期
多線程在線程池中主要有下圖這幾種狀態(tài):當創(chuàng)建后,有任務就會被CPU調(diào)度为障,執(zhí)行任務晦闰,此時可能阻塞,任務執(zhí)行完畢就退出鳍怨。
阻塞之后如果需要會再次添加到線程池中呻右,等待下次調(diào)度。
image.png
8鞋喇、線程添加到線程池
線程添加到線程池是有原則的声滥,因為線程池的大小是一定的。
主要條件有三個:
- 核心線程池大小侦香。如果線程池的大小小于核心線程池落塑,那么可以創(chuàng)建線程;
- 工作隊列罐韩。如果工作隊列已經(jīng)未滿憾赁,那么添加到隊列,創(chuàng)建線程伴逸;
-
線程是否都工作缠沈。如果沒有都工作,那么創(chuàng)建線程错蝴。
image.png
飽和策略
蘋果提供了api可以進行設置
- 中止
- 拋棄
- 退回
- 等待
- push
線程和RunLoop的關系
- runloop與線程是一一對應的,一個runloop對應一個核心的線程颓芭,為什么說是核心的顷锰,是因為runloop是可以嵌套的,但是核心的只能有一個亡问,他們的關系保存在一個全局的字典里官紫。
- runloop是來管理線程的肛宋,當線程的runloop被開啟后,線程會在執(zhí)行完任務后進入休眠狀態(tài)束世,有了任務就會被喚醒去執(zhí)行任務酝陈。
- runloop在第一次獲取時被創(chuàng)建,在線程結(jié)束時被銷毀毁涉。
- 對于主線程來說沉帮,runloop在程序一啟動就默認創(chuàng)建好了。
- 對于子線程來說贫堰,runloop是懶加載的穆壕,只有當我們使用的時候才會創(chuàng)建,所以在子線程用定時器要注意:確保子線程的runloop被創(chuàng)建其屏,不然定時器不會回調(diào)喇勋。
RunLoop和線程在一個字典中呈現(xiàn)一一對應的關系,其中線程的指針為key偎行;RunLoop使得線程存活川背,也就是常駐;線程退出時使得RunLoop結(jié)束蛤袒。
C于OC的橋接小知識
- __bridge只做類型轉(zhuǎn)換熄云,但是不修改對象(內(nèi)存)管理權(quán);
- __bridge_retained(也可以使用CFBridgingRetain)將Objective-C的對象轉(zhuǎn)換為Core Foundation的對象汗盘,同時將對象(內(nèi)存)的管理權(quán)交給我們皱碘,后續(xù)需要使用CFRelease或者相關方法來釋放對象;
- __bridge_transfer(也可以使用CFBridgingRelease)將Core Foundation的對象轉(zhuǎn)換為Objective-C的對象隐孽,同時將對象(內(nèi)存)的管理權(quán)交給ARC癌椿。
為什么要在主線程更新UI?
蘋果就是這樣設計的菱阵,這是一套設計的標準踢俄。
蘋果要求在主線程中更新UI操作,操作系統(tǒng)便于執(zhí)行;
為了用戶體驗,一些UI上的交互肯定是給用戶直接交互比較好症副,多數(shù)情況下喉前,UI是直接展現(xiàn)給用戶的,所以在主線程展示不至于卡頓或者突兀似枕。
如何辦到的手動控制線程生命周期
因為GCD完全是自動控制線程生命周期,只需要將任務交給他執(zhí)行,執(zhí)行完畢會自動控制銷毀歌懒,所以有時候并不能完全滿足我們的要求,比如有時候我們想要取消正在執(zhí)行的任務時溯壶。所以一般可以重寫start等方法來實現(xiàn)及皂。