iOS 多線程的概念、原理

圖1.png

線程和進程的關係和區別

線程定義
  • 線程是進程的基本執行單元,一個進程的全部任務都在線程中執行
  • 進程要想執行任務,必須得有線程,進程至少要有一條線程
  • 程序啓動會默認開啓一條線程,這條線程被稱爲主線程或 UI 線程
進程定義
  • 進程是指在系統中正在運行的一個應用程序ios

  • 每一個進程之間是獨立的,每一個進程均運行在其專用的且受保護的內存空間內macos

  • 經過「活動監視器」能夠查看 Mac 系統中所開啓的進程 #####進程與線程的區別安全

  • 地址空間:同一進程的線程共享本進程的地址空間,而進程之間則是獨立的地址空間。bash

  • 資源擁有:同一進程內的線程共享本進程的資源如內存、I/O、cpu等,可是進程之間的資源是獨立的。網絡

  • 一個進程崩潰後,在保護模式下不會對其餘進程產生影響,可是一個線程崩潰整個進程都死掉。因此多進程要比多線程健壯。多線程

  • 進程切換時,消耗的資源大,效率高。因此涉及到頻繁的切換時,使用線程要好於進程。一樣若是要求同時進行而且又要共享某些變量的併發操做,只能用線程不能用進程併發

  • 執行過程:每一個獨立的進程有一個程序運行的入口、順序執行序列和程序入口。可是線程不能獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。性能

  • 線程是處理器調度的基本單位,可是進程不是。ui

多線程的意義

優勢

  • 能適當提升程序的執行效率
  • 能適當提升資源的利用率(CPU,內存)
  • 線程上的任務執行完成後,線程會自動銷燬

缺點

  • 開啓線程須要佔用必定的內存空間(默認狀況下,每個線程都佔 512 KB)
  • 若是開啓大量的線程,會佔用大量的內存空間,下降程序的性能
  • 線程越多,CPU 在調用線程上的開銷就越大
  • 程序設計更加複雜,好比線程間的通訊、多線程的數據共享
    圖2.png

好像主線程也是512KB,而不是1MBspa

多線程的原理

圖3.png

多線程的生命週期

圖4.png

  • 新建線程,執行start,線程必須start,不然沒有做用。但也不能夠重複start,會致使崩潰
  • 線程start後,將會進入Runnable狀態。
  • 進入Runnable狀態後,進入Running狀態,當前線程會被CPU調度。也有可能在進入Running狀態後,線程切換,返回Runnable狀態

CPU如何調度線程?線程池的原理

圖5-線程池參數.png
圖6-線程池的原理.png
1.系統有一個可調度線程池,若是線程池裏有這個線程,就會開始執行。 2.若是沒有,將判斷線程池大小是否小於核心線程池大小,若是小於,那將會開闢新的線程來執行任務。 3.若是大於線程池,表明線程池沒有能力再去開闢新的線程,只能依賴於原有的線程去執行 ,就將判斷工做隊列是否已滿,若是沒滿就將任務提交到工做隊列,等待執行任務。 4.滿了的話,線程池就會判斷全部線程是否都在工做,若是有空閒的線程,就讓這條線程去執行任務。 5.若是仍是沒有空閒的線程,就將任務交給 飽和策略。 6.飽和策略分爲四種

Abort策略:默認策略,新任務提交時直接拋出未檢查的異常RejectedExecutionException,該異常可由調用者捕獲。 CallerRuns策略:爲調節機制,既不拋棄任務也不拋出異常,而是將某些任務回退到調用者。不會在線程池的線程中執行新的任務,而是在調用exector的線程中運行新的任務。 Discard策略:新提交的任務被拋棄。 DiscardOldest策略:隊列的是「隊頭」的任務,而後嘗試提交新的任務。(不適合工做隊列爲優先隊列場景)

  • Running後,有可能任務會形成堵塞,當形成堵塞的任務執行結束後,一樣會回到Runnable狀態,繼續執行Running
  • 死亡,分爲任務執行結束跟強制退出線程exit

線程操做

查看NSThread相關文件能夠看到,線程有多種狀態,能夠根據不一樣狀況,判斷線程的狀態,來作不一樣的操做。可經過重寫下面的方法掌握線程的生命週期(YYKit)。 通常狀況下,咱們不多去停止一個網絡請求,按照通常的狀況,是沒辦法停止的,可是依靠線程,經過關閉線程,從而達到停止網絡請求的目的。

@property (readonly, getter=isExecuting) BOOL executing API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
@property (readonly, getter=isFinished) BOOL finished API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
@property (readonly, getter=isCancelled) BOOL cancelled API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));

- (void)cancel API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
- (void)start API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
- (void)main API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));	// thread body method
複製代碼

線程安全

這是一張經典的多線程比喻圖。多端增刪改查。

圖7.png

如何避免上圖的狀況?如何保證線程安全? 上鎖

相關文章
相關標籤/搜索