iOS-DispatchQueue in Swift

Gordon Feng
程式愛好者
Published in
Jan 27, 2022
Imagine there is a lot of minion, working in DispatchQueue for us.

“An object that manages the execution of tasks serially or concurrently on your app’s main thread or on a background thread.”

依照Apple Documentation描述,DispatchQueue是一個決定在App主執行緒(Main thread)或背景執行緒(Background thread)下,我們的任務(Task)應該要同步(serially)執行或非同步(concurrently)執行。

以下我們會對這些專有名詞進行介紹

主執行緒(Main thread)與背景執行緒(Background thread)

主執行緒:
主要處理UI畫面更新的Task。
系統會自動創建此唯一的DispatchQueue.main管理Main thread,若任何時候阻塞主執行緒造成主執行緒延遲,導致Main thread太久沒有回應,系統會直接把App閃退掉。

背景執行緒:
處理UI以外的事物,通常是需要耗時的Task,諸如call API等等,若你在背景執行緒上執行畫面更新,可能會發生延遲現象導致使用者體驗不佳,但若在建立UI物件、或是畫面更新前的準備動作,就可以在背景執行緒進行。

DispatchQueue.global可分配非同步的背景執行緒,並設定Thread的qos(Quality of Service),系統所提供的資源量會以qos優先權為基準,優先權越高,系統提供的資源量越多。

執行優先權順序由高到低分為以下五種:

  1. UserInteractive:專門使用在與使用者互動的任務,例如動畫、事件處理、更新畫面等等
  2. UserInitialed:避免使用者過分頻繁操作你的App時
  3. Default:預設的優先權
  4. Utility:使用在使用者不需要持續追蹤的事件處理
  5. Background :需要對你所創的任務進行維護或清除的時候使用

同步(Serial)與非同步(Concurrent)

同步執行(Sync):指的是在一個任務結束後,才會呼叫下一個任務開始執行,以先進先出(FIFO)的方式有順序的完成所有任務。

非同步執行(Async):指的是不需要等待任何任務,任務之間的開始與結束不互相依賴,設定為Sync的Queue在每一次收到一個task後,將收到的任務丟到獨立的thread執行,任務之間非同步進行,並依照不同任務完成的先後,無特定順序的完成所有任務。

舉個例子來說:

Difference between Seriously and Concurrently.

Line 1: 我們創造一個背景執行緒
Line 3–7: 我們模擬一個任務所需要執行的時間為1–3秒不等,並標示著任務的開始與結束

Line 9–13: 模擬同步執行
Line 15–19: 模擬非同步執行

執行結果:

Result of serious and concurrent execution

由上圖可以發現,已同步執行,所有程式碼會在同一個執行緒內排隊執行,但若設定非同步執行,每個任務都會分配不同的執行緒分別執行。

必須要注意的是:若在非同步狀態下堵塞執行緒,系統無法將這條執行緒給其他任務使用時,系統必須要另開新執行緒,而這些過多堵塞執行緒可能會造成系統用盡所有資源而閃退。

佇列(Queue)與執行緒(Thread)

Thread
分為兩種,Main thread 跟Background thread,Main thread在系統中只會有一條,而Background thread則可以有很多條。

Queue
發送Task給系統的物件,Queue在接收到Task後,會負責將接收到的Task依照所設定的規則(同步或非同步、Qos…)發送給系統。
管理Thread的分配會由系統負責,系統將Task分派到對應的Thread後,這條Thread會被分配到系統CPU的核心,去執行身上的任務。

值得注意的是,除了Main thread外,系統並不保證Task可以在特定哪一條Thread上執行。

--

--