天天看點

iOS GCD(Grand Central Dispatch)的使用(1)

靈活: GCD 具有在常見模式上(比如鎖、單例),用更高性能的方法優化代碼,而且 GCD 能提供更多的控制權力以及大量的底層函數。

性能: GCD 能自動根據系統負載來增減線程數量,這就減少了上下文切換以及增加了計算效率。

Dispatch Objects:

GCD是純C語言的,但它被組建成面向對象的風格。GCD對象被稱為dispatch object, 所有的dispatch objects都是OC對象.,就如其他OC對象一樣,當開啟了ARC(automatic reference counting)時,dispatch objects的retain和release都會自動執行。而如果是MRC的話,dispatch objects會使用dispatch_retain和dispatch_release這兩個方法來控制引用計數。

Serial & Concurrent:

串行任務就是每次隻有一個任務被執行,并發任務就是在同一時間可以有多個任務被執行。

Synchronous & Asynchronous:

同步函數 意思是在完成了它預定的任務後才傳回,在任務執行時會阻塞目前線程。而 異步函數 則是任務會完成但不會等它完成,是以異步函數不會阻塞目前線程,會繼續去執行下一個函數。

Context Switch:

Context Switch即上下文切換,一個上下文切換指當你在單個程序裡切換執行不同的線程時存儲與恢複執行狀态的過程。這個過程在編寫多任務應用時很普遍,但會帶來一些額外的開銷。

Dispatch Queues:

GCD dispatch queues是一個強大的執行多任務的工具。Dispatch queue是一個對象,它可以接受任務,并将任務以先進先出(FIFO)的順序來執行。Dispatch queue可以并發的或串行的執行任意一個代碼塊,而且并發任務會像NSOperationQueue那樣基于系統負載來合适地并發進行,串行隊列同一時間則隻執行單一任務。Dispatch queues内部使用的是線程,GCD 管理這些線程,并且使用Dispatch queues的時候,我們都不需要自己建立線程。Dispatch queues相對于和線程直接通信的代碼優勢是:Dispatch queues使用起來特别友善,執行任務更加有效率。

(1) 主線程隊列: main queue可以調用dispatch_get_main_queue()來獲得。因為main queue是與主線程相關的,是以這是一個串行隊列。和其它串行隊列一樣,這個隊列中的任務一次隻能執行一個。它能保證所有的任務都在主線程執行,而主線程是唯一可用于更新 UI 的線程。

(2) 并發隊列: 并發隊列雖然是能同時執行多個任務,但這些任務仍然是按照先到先執行(FIFO)的順序來執行的。并發隊列會基于系統負載來合适地選擇并發執行這些任務。在iOS5之前,并發隊列一般指的就是全局隊列(Global queue),程序中存在四個全局隊列:高、中(預設)、低、背景四個優先級隊列,可以調用dispatch_get_global_queue函數傳入優先級來通路隊列。而在iOS5之後,我們也可以用dispatch_queue_create,并指定隊列類型DISPATCH_QUEUE_CONCURRENT,來自己建立一個并發隊列。

(3) 串行隊列: 串行隊列将任務以先進先出(FIFO)的順序來執行,是以串行隊列經常用來做通路某些特定資源的同步處理。你可以也根據需要建立多個隊列,而這些隊列相對其他隊列都是并發執行的。換句話說,如果你建立了4個串行隊列,每一個隊列在同一時間都隻執行一個任務,對這四個任務來說,他們是互相獨立且并發執行的。如果需要建立串行隊列,一般用dispatch_queue_create這個方法來實作。

介紹完基本概念,我們看看如何使用…..

(1) global queue(全局隊列):

當我們需要同時執行多個任務時,并發隊列是非常有用的。并發隊列其實仍然還是一個隊列,它保留了隊列中的任務按先進先出(FIFO)的順序執行的特點。一個并發隊列中實際執行的任務數是由很多因素決定的,比如系統的核心數,其他串行隊列中任務的優先級,以及其他程序的工作狀态。<code>但是global queue 對于 dispatch_suspend(暫停)、dispatch_resume(恢複)、dispatch_set_context(切換上下文)函數無響應</code>

我們來看一看 dispatch queue隊列的優先級都有哪些

#define DISPATCH_QUEUE_PRIORITY_HIGH 2 //高 #define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 //預設 #define DISPATCH_QUEUE_PRIORITY_LOW (-2) //低 #define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN //背景

注意:

盡管dispatch queues是引用計數對象,但是我們不需要用retain和release來管理全局的并發隊列。因為全局隊列對于程式來說是全局的,retain和release會被全局隊列忽略,而且在ARC下這兩個方法也會被忽略的。是以,我們不需要存儲這些隊列的引用數,僅僅隻需要在任何要使用它們的地方,調用dispatch_get_global_queue這個方法即可。

(2) 并發隊列和串行隊列

當我們需要某些任務以指定的順序去執行時,串行隊列是一個非常好的選擇。一個串行隊列在同一時間裡隻會執行一個任務,而且每次都隻會從隊列的頭部把任務取出來執行。正因為如此,我們可以用串行隊列來替代鎖的操作,比如資料資源的同步或修改資料結構時。和鎖不同的是,串行隊列能保證任務都是在可預見的順序裡執行,而且一旦我們在一個串行隊列裡異步送出了任務,隊列就能永遠不發生死鎖。怎麼樣,是不是很棒,不過不像并發隊列,這些串行隊列是需要我們自己建立和管理的。

我們還可以在程式裡建立任意數量的隊列,不過值得注意的是,我們要盡量避免建立大量的串行隊列而目的僅僅是為了同時執行隊列中的這些任務。雖然GCD 通過建立所謂的線程池來大緻比對 CPU 核心數量,但是線程的建立并不是無代價的。每個線程都需要占用記憶體和核心資源。是以如果需要建立大量的并發任務,我們隻需要把這些任務放到并發隊列中即可。

本文轉自 卓行天下  51CTO部落格,原文連結:http://blog.51cto.com/9951038/1932773,如需轉載請自行聯系原作者