歡迎閱讀iOS探索系列(按序閱讀食用效果更加)前端
多線程在iOS中有着舉足輕重的地位,不要覺得UI仔就不須要了解線程了,不光能在面試中吹噓兩句,使用得當更能保證app的質量android
進程
是指在系統中正在運行的一個應用程序,如微信、支付寶app都是一個進程進程
之間是獨立的,每一個進程
均運行在齊專用的且受保護的內存線程
是進程
的基本執行單元,一個進程
的全部任務都在線程中執行進程
想要執行任務,必須得有線程
,進程
至少要有一條線程
線程
,這條線程
被成爲主線程
或UI線程
進程
的線程
共享本進程的地址空間,而進程之間則是獨立的地址空間進程
內的線程
共享本進程的資源如內存、I/O、cpu等,可是進程
之間的資源是獨立的進程
崩潰後,在保護模式下不會對其餘進程
產生影響,可是一個線程
崩潰整個進程
都死掉,因此多進程
要比多線程
健壯進程
切換時,消耗的資源大、效率高。因此設計到頻繁的切換時,使用線程
要好於進程
。一樣若是要求同時進行而且又要共享某些變量的併發操做,只能用線程
而不能用進程
進程
有一個程序運行的入口、順序執行序列和程序入口。可是線程
不能獨立執行,必須依存在應用程序中,由應用程序提供多個線程
執行控制線程
是處理器調度的基本單位,但進程
不是可能會以爲這些理論知識很抽象,百度出來一大堆可是都很差理解,看完下面的理解就全明白了程序員
iOS系統
想象成
商場
,
進程
則是商場中的
店鋪
,
線程
是店鋪僱傭的
員工
:
移動開發不必定是單進程處理的,android就是多進程處理的;而iOS採用沙盒機制,這也是蘋果運行可以流暢安全的一個主要緣由面試
隊列,又稱爲佇列(queue
),是先進先出(FIFO: First-In-First-Out
)的線性表,在具體應用中一般用鏈表或者數組來實現。裝載線程任務的隊形結構。隊列只容許在後端(稱爲rear
)進行插入操做,在前端(稱爲front
)進行刪除操做。隊列的操做方式和堆棧相似,惟一的區別在於隊列只容許新數據在後端進行添加 後端
關於隊列會在下一篇文章詳細介紹數組
二者是沒有關係的,能夠這麼理解:安全
隊列
負責調度任務,線程
執行任務微信
在銀行(進程
)中,有4個工做窗口(線程
),而只有一條隊伍(隊列
)多線程
窗口(線程
)只負責爲排隊的人辦理業務,並不會管隊伍(隊列
)是怎麼排的併發
runloop與線程是一一對應的
——一個runloop
對應一個核心的線程
,爲何說是核心的,是由於runloop是能夠嵌套的,可是核心的只能有一個,他們的關係保存在一個全局的字典裏runloop是來管理線程的
——當線程的runloop
被開啓後,線程會在執行完任務後進入休眠狀態,有了任務就會被喚醒去執行任務runloop
在第一次獲取時被建立,在線程結束時被銷燬
runloop
在程序一啓動就默認建立好了runloop
是懶加載的——只有當咱們使用的時候纔會建立,因此在子線程用定時器要注意:確保子線程的runloop
被建立,否則定時器不會回調如下因素都會對任務的執行速度形成影響:
512KB
,建立線程大約須要90毫秒
的建立時間)新建
:實例化線程對象就緒
:向線程對象發送start消息,線程對象被加入可調度線程池等待CPU調度。運行
:CPU 負責調度可調度線程池中線程的執行。線程執行完成以前,狀態可能會在就緒和運行之間來回切換。就緒和運行之間的狀態變化由CPU負責,程序員不能干預。阻塞
:當知足某個預約條件時,可使用休眠或鎖,阻塞線程執行。sleepForTimeInterval
(休眠指定時長),sleepUntilDate
(休眠到指定日期),@synchronized(self):
(互斥鎖)。死亡
:正常死亡,線程執行完畢。非正常死亡,當知足某個條件後,在線程內部停止執行/在主線程停止線程對象線程池大小
小於核心線程池大小
時
線程池大小
大於等於核心線程池大小
時
maximumPoolSize>corePoolSize
,將建立新的線程來執行任務飽和策略
去處理參數名 | 表明意義 |
---|---|
corePoolSize | 線程池的基本大小(核心線程池大小) |
maximumPool | 線程池的最大大小 |
keepAliveTime | 線程池中超過corePoolSize樹木的空閒線程的最大存活時間 |
unit | keepAliveTime參數的時間單位 |
workQueue | 任務阻塞隊列 |
threadFactory | 新建線程的工廠 |
handler | 當提交的任務數超過maxmumPoolSize與workQueue之和時, 任務會交給RejectedExecutionHandler來處理 |
飽和策略有以下四個:
AbortPolicy
直接拋出RejectedExecutionExeception異常來阻止系統正常運行CallerRunsPolicy
將任務回退到調用者DisOldestPolicy
丟掉等待最久的任務DisCardPolicy
直接丟棄任務技術方案 | 簡介 | 語言 | 線程生命週期 | 使用評率 |
---|---|---|---|---|
pthread | 一套通用的多線程API 適用於Unix/Linux/Windows等系統 跨平臺/可移植 使用難度大 |
C | 程序員管理 | 幾乎不用 |
NSThread | 使用更加面向對象 簡單易用,可直接操做線程對象 |
OC | 程序員管理 | 偶爾使用 |
GCD | 旨在替代NSThread等線程技術 充分利用設備的多核 |
C | 自動管理 | 常用 |
NSOperation | 基於GCD(底層是GCD) 比GCD多了一些更簡單實用的功能 使用更加面向對象 |
OC | 自動管理 | 常用 |
GCD
僅僅支持FIFO
隊列,不支持異步操做之間的依賴關係設置。而NSOperation
中的隊列能夠被從新設置優先級,從而實現不一樣操做的執行順序調整NSOperation
支持KVO
,能夠觀察任務的執行狀態GCD
更接近底層,GCD
在追求性能的底層操做來講,是速度最快的GCD
須要本身寫更多的代碼來實現,而NSOperation
已經內建了這些支持NSOperation
更好;底層代碼中,任務之間不太互相依賴,而須要更高的併發能力,GCD
則更有優點直接消息傳遞
: 經過performSelector
的一系列方法,能夠實現由某一線程指定在另外的線程上執行任務。由於任務的執行上下文是目標線程,這種方式發送的消息將會自動的被序列化全局變量、共享內存塊和對象
: 在兩個線程之間傳遞信息的另外一種簡單方法是使用全局變量,共享對象或共享內存塊。儘管共享變量既快速又簡單,可是它們比直接消息傳遞更脆弱。必須使用鎖或其餘同步機制仔細保護共享變量,以確保代碼的正確性。 不然可能會致使競爭情況,數據損壞或崩潰。條件執行
: 條件是一種同步工具,可用於控制線程什麼時候執行代碼的特定部分。您能夠將條件視爲關守,讓線程僅在知足指定條件時運行。Runloop sources
: 一個自定義的 Runloop source 配置可讓一個線程上收到特定的應用程序消息。因爲 Runloop source 是事件驅動的,所以在無事可作時,線程會自動進入睡眠狀態,從而提升了線程的效率Ports and sockets
:基於端口的通訊是在兩個線程之間進行通訊的一種更爲複雜的方法,但它也是一種很是可靠的技術。更重要的是,端口和套接字可用於與外部實體(例如其餘進程和服務)進行通訊。爲了提升效率,使用 Runloop source 來實現端口,所以當端口上沒有數據等待時,線程將進入睡眠狀態消息隊列
: 傳統的多處理服務定義了先進先出(FIFO)隊列抽象,用於管理傳入和傳出數據。儘管消息隊列既簡單又方便,可是它們不如其餘一些通訊技術高效Cocoa 分佈式對象
: 分佈式對象是一種 Cocoa 技術,可提供基於端口的通訊的高級實現。儘管能夠將這種技術用於線程間通訊,可是強烈建議不要這樣作,由於它會產生大量開銷。分佈式對象更適合與其餘進程進行通訊,儘管在這些進程之間進行事務的開銷也很高本文初步介紹了多線程,下篇文章講解多線程中的主角——GCD