GCD - 隊(duì)列管理

dispatch_queue_t

隊(duì)列對(duì)應(yīng)一個(gè)dispatch_queue_t對(duì)象即:

dispatch_queue_t queue;

類似普通OC對(duì)象,可以用dispatch_retain()和dispatch_release()對(duì)其進(jìn)行內(nèi)存管理,當(dāng)一個(gè)任務(wù)加入到一個(gè)queue中的時(shí)候,任務(wù)會(huì)retain這個(gè)queue,直到任務(wù)執(zhí)行完成才會(huì)release。iOS6之后dispatch對(duì)象已經(jīng)支持ARC,所以在ARC工程之下,我們可以不用擔(dān)心他的內(nèi)存。

一般情況下只需要用strong申明一個(gè)dispatch的屬性。

@property (nonatomic, strong) dispatch_queue_t queue;

如果你是寫(xiě)一個(gè)framework,framework的使用者的SDK有可能還是古董級(jí)的iOS6之前。那么你需要根據(jù)OS_OBJECT_USE_OBJC做一個(gè)判斷是使用strong還是assign。(一般github上的優(yōu)秀第三方庫(kù)都會(huì)這么做)

#if OS_OBJECT_USE_OBJC
@property (nonatomic, strong) dispatch_queue_t queue;
#else
@property (nonatomic, assign) dispatch_queue_t queue;
#endif

<li><h4>獲取主線程隊(duì)列<h4></li>

主線程是我們最常用的線程,獲取主線程隊(duì)列的方法很簡(jiǎn)單:

dispatch_queue_t mainQueue;
mainQueue = dispatch_get_main_queue();

假設(shè)要在主線程更新UI:

dispatch_async(dispatch_get_main_queue(), ^{
    [self updateUI];
});

執(zhí)行加入到主線程隊(duì)列的block,App會(huì)調(diào)用dispatch_main(), NSApplicationMain(),或者在主線程使用CFRunLoop。

<li><h4>獲取全局隊(duì)列<h4></li>

除了主線程隊(duì)列,GCD提供了幾個(gè)全局隊(duì)列,可以直接獲取使用

dispatch_queue_t dispatch_get_global_queue(long identifier, unsigned long flags);

dispatch_get_global_queue方法獲取的全局隊(duì)列都是并行隊(duì)列,并且隊(duì)列不能被修改,也就是說(shuō)對(duì)全局隊(duì)列調(diào)用dispatch_suspend(), dispatch_resume(), dispatch_set_context()等方法無(wú)效。

全局隊(duì)列對(duì)于程序來(lái)說(shuō)是全局的,retain和release會(huì)被全局隊(duì)列忽略。所以,我們不需要存儲(chǔ)這些隊(duì)列的引用數(shù)。

identifier: 用以標(biāo)識(shí)隊(duì)列優(yōu)先級(jí),推薦用qos_class枚舉作為參數(shù),也可以使用dispatch_queue_priority_t

flags: 預(yù)留字段,傳入任何非0的值都可能導(dǎo)致返回NULL

代碼示例:

dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

全局隊(duì)列的四種類型

DISPATCH_QUEUE_PRIORITY_HIGH : 最高優(yōu)先級(jí),交互級(jí)別。使用這個(gè)優(yōu)先級(jí)會(huì)占用幾乎所有的系統(tǒng)CUP和I/O帶寬,僅限用于交互的UI操作,比如處理點(diǎn)擊事件,繪制圖像到屏幕上,動(dòng)畫(huà)等

DISPATCH_QUEUE_PRIORITY_DEFAULT : 默認(rèn)優(yōu)先級(jí),當(dāng)沒(méi)有設(shè)置優(yōu)先級(jí)的時(shí)候,線程默認(rèn)優(yōu)先級(jí)。一般情況下用的都是這個(gè)優(yōu)先級(jí)

DISPATCH_QUEUE_PRIORITY_LOW : 普通優(yōu)先級(jí),主要用于不需要立即返回的任務(wù)

DISPATCH_QUEUE_PRIORITY_BACKGROUND : 后臺(tái)優(yōu)先級(jí),用于用戶幾乎不感知的任務(wù)。它會(huì)等待所有比它級(jí)別高的隊(duì)列中的任務(wù)執(zhí)行完或CPU空閑的時(shí)候才會(huì)執(zhí)行自己的任務(wù)。例如磁盤的讀寫(xiě)操作非常耗時(shí),如果我們不需要立即獲取到磁盤的數(shù)據(jù),我們可以把讀寫(xiě)任務(wù)放到后臺(tái)隊(duì)列中,這樣讀寫(xiě)任務(wù)只會(huì)在恰當(dāng)?shù)臅r(shí)候去執(zhí)行而不會(huì)影響需要更改優(yōu)先級(jí)的其他任務(wù),整個(gè)程序也會(huì)更加有效率。

由于NULL等于0,也就是DISPATCH_QUEUE_PRIORITY_DEFAULT,所以將0或者NULL傳入作為參數(shù)返回的是默認(rèn)優(yōu)先級(jí):

dispatch_get_global_queue(NULL, NULL)

<li><h4>創(chuàng)建串行隊(duì)列&并發(fā)隊(duì)列<h4></li>
當(dāng)無(wú)法獲取到理想的隊(duì)列時(shí),我們可以自己創(chuàng)建隊(duì)列:

dispatch_queue_t dispatch_queue_create(const char *label, dispatch_queue_attr_t attr);

label: 隊(duì)列的名稱,調(diào)試的時(shí)候可以區(qū)分其他的隊(duì)列

attr: 隊(duì)列的屬性,dispatch_queue_attr_t類型。用以標(biāo)識(shí)隊(duì)列串行,并行,以及優(yōu)先級(jí)等信息

attr參數(shù)有三種傳值方式:

// 串行
#define DISPATCH_QUEUE_SERIAL NULL
 
// 并行
#define DISPATCH_QUEUE_CONCURRENT \
        DISPATCH_GLOBAL_OBJECT(dispatch_queue_attr_t, \
        _dispatch_queue_attr_concurrent)
         
// 自定義屬性值
dispatch_queue_attr_t dispatch_queue_attr_make_with_qos_class(dispatch_queue_attr_t attr, dispatch_qos_class_t qos_class, int relative_priority);

DISPATCH_QUEUE_SERIAL 或者 NULL,表示創(chuàng)建串行隊(duì)列,優(yōu)先級(jí)為目標(biāo)隊(duì)列優(yōu)先級(jí)。

DISPATCH_QUEUE_CONCURRENT,表示創(chuàng)建并行隊(duì)列,優(yōu)先級(jí)也為目標(biāo)隊(duì)列優(yōu)先級(jí)。

另外, 自定義屬性值
dispatch_queue_attr_make_with_qos_class函數(shù)可以創(chuàng)建帶有優(yōu)先級(jí)的dispatch_queue_attr_t對(duì)象。通過(guò)這個(gè)對(duì)象可以自定義queue的優(yōu)先級(jí)。

attr: 傳入DISPATCH_QUEUE_SERIAL、NULL或DISPATCH_QUEUE_CONCURRENT,表示串行或者并行

qos_class: 傳入qos_class枚舉,表示優(yōu)先級(jí)級(jí)別

relative_priority: 相對(duì)于qos_class的相對(duì)優(yōu)先級(jí),qos_class用于區(qū)分大的優(yōu)先級(jí)級(jí)別,relative_priority表示大級(jí)別下的小級(jí)別。relative_priority必須大于QOS_MIN_RELATIVE_PRIORITY小于0,否則將返回NULL。從GCD源碼中可以查到QOS_MIN_RELATIVE_PRIORITY等于-15

使用dispatch_queue_attr_make_with_qos_class創(chuàng)建隊(duì)列時(shí),需要注意,非法的參數(shù)可能導(dǎo)致dispatch_queue_attr_make_with_qos_class返回NULL,dispatch_queue_create傳入NULL會(huì)創(chuàng)建出串行隊(duì)列。寫(xiě)代碼過(guò)程中需要確保這是否是預(yù)期的結(jié)果

常用創(chuàng)建隊(duì)列代碼示例:

  //串行隊(duì)列
   dispatch_queue_t serialQueue;
   serialQueue = dispatch_queue_create("com.example.SerialQueue", NULL);

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

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

  • GCD (Grand Central Dispatch) :iOS4 開(kāi)始引入,使用更加方便,程序員只需要將任務(wù)添...
    池鵬程閱讀 1,443評(píng)論 0 2
  • GCD(Grand Central Dispatch) 介紹 GCD 屬于系統(tǒng)級(jí)的線程管理,在 Dispatch ...
    fuyoufang閱讀 4,883評(píng)論 0 10
  • 一、在后臺(tái)工作量少 當(dāng)用戶沒(méi)有主動(dòng)使用你的應(yīng)用程序時(shí),系統(tǒng)會(huì)將其轉(zhuǎn)換為背景狀態(tài)。該系統(tǒng)最終可能會(huì)暫停您的應(yīng)用程序,...
    弗利撒閱讀 991評(píng)論 1 0
  • 多線程是程序開(kāi)發(fā)中非?;A(chǔ)的一個(gè)概念,大家在開(kāi)發(fā)過(guò)程中應(yīng)該或多或少用過(guò)相關(guān)的東西。同時(shí)這恰恰又是一個(gè)比較棘手的概念...
    小笨狼閱讀 7,159評(píng)論 12 70
  • 基于自 raywenderlich.com 在2015年的兩篇文章 Grand Central Dispatch ...
    seedante閱讀 1,468評(píng)論 0 7

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