YYDispatchQueuePool學習

YYDispatchQueuePool YYKit 中用來控控制全局線程數(shù)的組件;

用法有下面兩種:

  // 1. 從全局的 queue pool 中獲取一個 queue
  dispatch_queue_t queue = YYDispatchQueueGetForQOS(NSQualityOfServiceUtility);
  // 2. 創(chuàng)建一個新的 serial queue pool
  YYDispatchQueuePool *pool = [[YYDispatchQueuePool alloc] initWithName:@"file.read" queueCount:5 qos:NSQualityOfServiceBackground];
  dispatch_queue_t queue = [pool queue];

NSQualityOfServiceiOS8.0 提供的描述優(yōu)先級的枚舉值, 主要有下面幾種:

NSQualityOfServiceUserInteractive
NSQualityOfServiceUserInitiated
NSQualityOfServiceUtility
NSQualityOfServiceBackground 
NSQualityOfServiceDefault

用來替代 GCD 中的dispatch_queue_priority_t

NSQualityOfServiceUserInteractive:最高優(yōu)先級, 用于處理 UI 相關的任務
NSQualityOfServiceUserInitiated:次高優(yōu)先級, 用于執(zhí)行需要立即返回的任務
NSQualityOfServiceUtility:普通優(yōu)先級,主要用于不需要立即返回的任務
NSQualityOfServiceBackground:后臺優(yōu)先級,用于處理一些用戶不會感知的任務
NSQualityOfServiceDefault:默認優(yōu)先級,當沒有設置優(yōu)先級的時候,線程默認優(yōu)先級

dispatch_queue_t YYDispatchQueueGetForQOS(NSQualityOfService qos)函數(shù)接收一個NSQualityOfService參數(shù)同時返回一個隊列;

函數(shù)內部又調用了另外一個函數(shù)static dispatch_queue_t YYDispatchContextGetQueue(YYDispatchContext *context);
YYDispatchContext結構體如下:

typedef struct {
    const char *name;
    void **queues;
    uint32_t queueCount;
    int32_t counter;
} YYDispatchContext;

context的獲取通過static YYDispatchContext *YYDispatchContextGetForQOS(NSQualityOfService qos)函數(shù)返回, 通過判斷不同的qos參數(shù)創(chuàng)建不同優(yōu)先級的context對象, context對象的創(chuàng)建, 放在了

static YYDispatchContext *YYDispatchContextCreate(const char *name, uint32_t queueCount, NSQualityOfService qos);

函數(shù)中, 這也是整個庫的核心函數(shù), 接收3個參數(shù): 隊列名、可用核心數(shù)、優(yōu)先級.

    ...
    if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0) {
        dispatch_qos_class_t qosClass = NSQualityOfServiceToQOSClass(qos);
        for (NSUInteger i = 0; i < queueCount; i++) {
            dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, qosClass, 0);
            dispatch_queue_t queue = dispatch_queue_create(name, attr);
            context->queues[i] = (__bridge_retained void *)(queue);
        }
    } else {
        long identifier = NSQualityOfServiceToDispatchPriority(qos);
        for (NSUInteger i = 0; i < queueCount; i++) {
            dispatch_queue_t queue = dispatch_queue_create(name, DISPATCH_QUEUE_SERIAL);
            dispatch_set_target_queue(queue, dispatch_get_global_queue(identifier, 0));
            context->queues[i] = (__bridge_retained void *)(queue);
        }
    }
    ...

這里對 iOS8.0系統(tǒng)之前和 iOS8.0以后進行了分別處理;

iOS8.0之前:
先調用dispatch_queue_create(name, DISPATCH_QUEUE_SERIAL);創(chuàng)建一個串行隊列, 再調用dispatch_set_target_queue(queue, dispatch_get_global_queue(identifier, 0));設置隊列的優(yōu)先級, identifierqos的對應關系如下:

    switch (qos) {
        case NSQualityOfServiceUserInteractive: return DISPATCH_QUEUE_PRIORITY_HIGH;
        case NSQualityOfServiceUserInitiated: return DISPATCH_QUEUE_PRIORITY_HIGH;
        case NSQualityOfServiceUtility: return DISPATCH_QUEUE_PRIORITY_LOW;
        case NSQualityOfServiceBackground: return DISPATCH_QUEUE_PRIORITY_BACKGROUND;
        case NSQualityOfServiceDefault: return DISPATCH_QUEUE_PRIORITY_DEFAULT;
        default: return DISPATCH_QUEUE_PRIORITY_DEFAULT;
    } 

iOS8.0之后:
直接通過dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, qosClass, 0);創(chuàng)建一個attr參數(shù), 再調用dispatch_queue_create(name, attr)創(chuàng)建隊列; qosClassqos的對應關系如下:

    switch (qos) {
        case NSQualityOfServiceUserInteractive: return QOS_CLASS_USER_INTERACTIVE;
        case NSQualityOfServiceUserInitiated: return QOS_CLASS_USER_INITIATED;
        case NSQualityOfServiceUtility: return QOS_CLASS_UTILITY;
        case NSQualityOfServiceBackground: return QOS_CLASS_BACKGROUND;
        case NSQualityOfServiceDefault: return QOS_CLASS_DEFAULT;
        default: return QOS_CLASS_UNSPECIFIED;
    }

queues 創(chuàng)建完成以后, 再設置queueCountname, 至此context對象創(chuàng)建完成.
回到YYDispatchContextGetQueue函數(shù):

static dispatch_queue_t YYDispatchContextGetQueue(YYDispatchContext *context) {
    // 原子操作, 自增counter
    uint32_t counter = (uint32_t)OSAtomicIncrement32(&context->counter);
    // 每次輪詢獲取不同的隊列
    void *queue = context->queues[counter % context->queueCount];
    return (__bridge dispatch_queue_t)(queue);
}

簡單測試一張圖片的下載可以看出:

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

相關閱讀更多精彩內容

友情鏈接更多精彩內容