iOS 多線程之基礎(chǔ)

在開始之前,先理解以下幾點(diǎn)
一、進(jìn)程和線程的區(qū)別和聯(lián)系:
1、地址資源:進(jìn)程有自己的內(nèi)存地址,進(jìn)程內(nèi)的線程可以共享進(jìn)程的內(nèi)存地址
2、資源分配和調(diào)度:進(jìn)程是系統(tǒng)進(jìn)行資源分配和擁有的基本單位,同一個進(jìn)程內(nèi)的線程可共享進(jìn)程的資源
3、線程是CPU調(diào)度的基本單位。
4、二者都可以并發(fā)執(zhí)行
二、多線程的意義
優(yōu)點(diǎn):
1、提高資源(CPU和內(nèi)存)利用率
2、提高程序的執(zhí)行效率
3、線程上的任務(wù)執(zhí)行完后,線程會自動銷毀
缺點(diǎn):
1、開辟線程需要占用一定的內(nèi)存空間(默認(rèn)每個線程占用512kb)
2、線程越多,CPU調(diào)度的開銷越大
三、多線程原理
多線程的并發(fā)執(zhí)行其實并不是同時執(zhí)行,而是CPU在不同的線程間頻繁切換,達(dá)到的“偽同時”效果。這是由于每一個分得CPU的任務(wù)都會有一個時間片,它執(zhí)行完時間片的時間,CPU就不屬于它們了,要等待再次分配。

拋出問題

問題1、主線程是做什么的?
答:主線程是iOS程序運(yùn)行后開辟的第一個線程,也叫UI線程,用來顯示/刷新UI界面和處理UI事件。
問題2、UI為什么要在主線程更新?
答:蘋果為了性能考慮,UIKit不是線程安全的,試想如果UI可以在子線程更新,那么如果有多個線程同時修改某個資源時將會出現(xiàn)很多莫名其妙的錯誤。
問題3、能不能把渲染放到子線程?怎么渲染
遺留問題。

線程和Runloop的關(guān)系

1、Runloop和線程是一一對應(yīng)的關(guān)系
2、Runloop是來管理線程的,當(dāng)線程的runloop被開啟后,線程執(zhí)行完任務(wù)會休眠,等下次有任務(wù)時再執(zhí)行任務(wù)。
3、線程在第一次創(chuàng)建是被開啟,在線程結(jié)束時銷毀
3、Runloop在子線程中默認(rèn)不開啟,需要手動操作才能開啟。注意NSTImer

線程池工作原理

系統(tǒng)中的線程屬于寶貴資源,合理運(yùn)用線程池,可以減少創(chuàng)建和銷毀線程的次數(shù),使得每個線程可以重復(fù)利用。

  • corePoolSize:線程池基本大?。ê诵木€程數(shù)量)
  • maximumPoolSize:線程池允許的最大線程數(shù)
  • keepAliveTime:當(dāng)線程池的線程數(shù)量大于corePoolSize時,空閑線程的最大存活時間
  • workQueue:存放任務(wù)的工作隊列
  • handler:超出線程范圍和隊列容量的任務(wù)的處理程序

線程池的工作流程:當(dāng)提交一個任務(wù)時,線程池會做出如下判斷
1、如果正在運(yùn)行的線程數(shù)量小于corePoolSize,馬上創(chuàng)建線程執(zhí)行任務(wù)。
2、如果正在運(yùn)行的線程數(shù)量大于等于corePoolSize,則放入工作隊列中。
3、如果不巧,工作隊列也滿了,而且正在運(yùn)行的線程數(shù)量小于maximumPoolSize,那么還是要創(chuàng)建線程立刻運(yùn)行這個任務(wù)。
4、如果正在運(yùn)行的線程數(shù)量大于等于maximumPoolSize,則交給飽和策略處理。
如圖所示

線程池工作原理 .png

當(dāng)線程池的線程執(zhí)行完任務(wù)以后,會從工作隊列取下一個任務(wù)執(zhí)行。
當(dāng)一個線程空閑,且正在運(yùn)行的線程數(shù)大于corePoolSize,則計時超過keepAliveTime線程就會被kill掉,所以當(dāng)線程池中任務(wù)都完成后,它最終會縮小到corePoolSize大小。

飽和策略

當(dāng)任務(wù)提交線程池失敗時,即當(dāng)前提交的任務(wù)數(shù)超過maxmumPoolSizeworkQueue之和時,就會交給飽和策略處理。
飽和策略有四種,AbortPolicy、CallerRunsPolicy、DiscardPolicy、DiscardOldestPolicy

策略 Description
AbortPolicy 中止策略,屬于默認(rèn)的飽和策略,該策略將拋出未檢查的RejectedExecutionException。調(diào)用者可以捕獲這個異常,然后根據(jù)需要編寫自己的處理代碼。
DiscardPolicy 拋棄策略,當(dāng)新提交的任務(wù)無法保存到隊列中等待執(zhí)行時,“拋棄(Discard)”策略會悄悄拋棄該任務(wù)。
DiscardOldestPolicy 拋棄下一個將被執(zhí)行的任務(wù),然后嘗試重新提交新的任務(wù)。(如果工作隊列是一個優(yōu)先隊列,那么“拋棄最舊的”策略將導(dǎo)致拋棄優(yōu)先級最高的任務(wù),因此最好不要將“拋棄最舊的”飽和策略和優(yōu)先隊列放在一起使用。)
CallerRunsPolicy 調(diào)用者策略,策略實現(xiàn)了一種調(diào)度機(jī)制,該策略既不會拋棄任務(wù),也不會拋出異常,而是將某些任務(wù)回退到調(diào)用者,從而降低新任務(wù)的流量。它不會在線程池的某個線程中執(zhí)行新提交的任務(wù),而是在一個調(diào)用了execute的線程中執(zhí)行該任務(wù)。如果采用有界隊列和“調(diào)用者運(yùn)行”飽和策略,當(dāng)線程池中的所有線程都被占用,并且工作隊列被填滿后,下一個任務(wù)會在調(diào)用execute時在主線程中執(zhí)行。由于執(zhí)行任務(wù)需要一定的時間,因此主線程至少在一段時間內(nèi)不能提交任何任務(wù),從而使得工作者線程有時間來處理完正在執(zhí)行的任務(wù)。在此期間,主線程不會調(diào)用accept,因此到達(dá)的請求將被保存在TCP層的隊列中而不是在應(yīng)用程序的隊列中。如果持續(xù)過載,那么TCP層將最終發(fā)現(xiàn)它的請求隊列被填滿,因此同樣會開始拋棄請求。當(dāng)服務(wù)器過載時,這種過載情況會逐漸向外蔓延開來——從線程池到工作隊列到應(yīng)用程序再到TCP層,最終達(dá)到客戶端,導(dǎo)致服務(wù)器在高負(fù)載下實現(xiàn)一種平緩的性能降低。

線程的生命周期

線程生命周期的每一步如下所示:

  • 1、新建:實例化線程對象
  • 2、就緒:調(diào)用start將線程加入可調(diào)度線程池,等待CPU調(diào)度(分配時間片)。
  • 3、運(yùn)行:CPU從可調(diào)度線程池中分配時間片給線程,線程在未執(zhí)行完畢情況下可能會在就緒運(yùn)行之間不斷切換,程序員無法干預(yù)。
  • 4、阻塞:線程有時會因為同步、鎖、sleep等方式阻塞。
  • 5、死亡:分為正常死亡(線程結(jié)束)和非正常死亡(線程終止)。
線程生命周期.png
多線程的四種技術(shù)方案

多線程有四種技術(shù)方案分別是pthread、NSThread、GCD和NSOperation,如下圖所示


多線程的幾種方式

我們一般使用比較多的是GCD,因為開發(fā)者只需要告訴 GCD 想要執(zhí)行什么任務(wù),不需要編寫任何線程管理代碼,但這也是GCD的不夠靈活的地方,我們無法監(jiān)控線程的各個狀態(tài),這也是很多大框架中使用NSOperation的原因,NSOperation相比GCD更加靈活,開發(fā)者可以通過KVO監(jiān)測Operation的狀態(tài),自定義NSOperation等。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • iOS多線程編程 基本知識 1. 進(jìn)程(process) 進(jìn)程是指在系統(tǒng)中正在運(yùn)行的一個應(yīng)用程序,就是一段程序的執(zhí)...
    陵無山閱讀 6,364評論 1 14
  • 又來到了一個老生常談的問題,應(yīng)用層軟件開發(fā)的程序員要不要了解和深入學(xué)習(xí)操作系統(tǒng)呢? 今天就這個問題開始,來談?wù)劜?..
    tangsl閱讀 4,332評論 0 23
  • 多線程 在iOS開發(fā)中為提高程序的運(yùn)行效率會將比較耗時的操作放在子線程中執(zhí)行,iOS系統(tǒng)進(jìn)程默認(rèn)啟動一個主線程,用...
    郭豪豪閱讀 2,726評論 0 4
  • 首先了解單線程:一、單線程的應(yīng)用,整個應(yīng)用中只有一個順序執(zhí)行流,當(dāng)執(zhí)行流在執(zhí)行某個耗時的操作,或者不能立即完成的任...
    甘哲157閱讀 716評論 1 8
  • 走親串友深山行, 山雨欲來風(fēng)云涌。 驚嘆遇上鬼天氣, 頻遭數(shù)襲黑旋風(fēng)。 急返失足溺水里, 有幸得救乃郎中。 平時功...
    太陽哥月亮妹閱讀 427評論 3 16

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