iOS實(shí)現(xiàn)創(chuàng)建一個(gè)全局長(zhǎng)駐隊(duì)列池

YYKit真是一個(gè)非常優(yōu)秀的框架!
最近看YYLabel源碼港粱,看到其中一段代碼非常有意思隔盛,作者在要display layer的守候獲取一個(gè)串行隊(duì)列,把繪制任務(wù)放入其中完成異步繪制沮翔。好的代碼自己也臨摹了一下陨帆,以做紀(jì)念。
1采蚀、創(chuàng)建兩個(gè)內(nèi)聯(lián)函數(shù)用于返回不同優(yōu)先級(jí)的狀態(tài)以及一個(gè)結(jié)構(gòu)體用于存儲(chǔ)不同優(yōu)先級(jí)下的隊(duì)列池疲牵,以及相關(guān)信息

//也就是說(shuō)建議編譯器將指定的函數(shù)體插入并取代每一處調(diào)用該函數(shù)的地方(上下文),從而節(jié)省了每次調(diào)用函數(shù)帶來(lái)的額外時(shí)間開支
static inline dispatch_queue_priority_t NSQualityOfServiceToDispatchPriority(NSQualityOfService qos){//<ios8
    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;
    }
}
static inline dispatch_qos_class_t NSQualityOfServiceToQOSClass(NSQualityOfService qos){//>ios8 其目的相同都是為了設(shè)置給隊(duì)列設(shè)置不同的優(yōu)先級(jí)榆鼠。
    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_DEFAULT;
    }
}

typedef struct  {
    int countCount;//隊(duì)列數(shù)量
    atomic_int counter;//原子計(jì)數(shù)器纲爸,用來(lái)記錄是第幾次取隊(duì)列
    void* *queues;//隊(duì)列數(shù)組
    char* name;//context name
}LHDispatchContext;

2、取隊(duì)列方法 其中我把原子計(jì)數(shù)方法替換成了 atomic_fetch_add_explicit妆够,蘋果iOS10后用此方法代替OSAtomicIncrement32

static dispatch_queue_t LHDispatchQueueGetFromContex(LHDispatchContext*contex){
    atomic_fetch_add_explicit(&contex->counter,1,memory_order_relaxed);//原子累加計(jì)數(shù)识啦,用于記錄此方法被訪問(wèn)次數(shù)
    int a =contex->counter%contex->countCount;//取余负蚊,為的是按順序取隊(duì)列,因?yàn)殛?duì)列是串行颓哮,這樣做的話提高效率家妆。
    return(__bridge dispatch_queue_t) contex->queues[a];
}

3、隊(duì)列創(chuàng)建方法的實(shí)現(xiàn)冕茅。NSQualityOfServiceToQOSClass伤极、NSQualityOfServiceToDispatchPriority 兩個(gè)函數(shù) 作者是用內(nèi)聯(lián)函數(shù)實(shí)現(xiàn)。提高效率姨伤。用于返回優(yōu)先級(jí)哨坪。

static LHDispatchContext* LHDispatchCreatQueue(char*name,int quneCount,NSQualityOfService qos){
    LHDispatchContext*contex =calloc(1, sizeof(LHDispatchContext));
    contex->countCount=quneCount;
    contex->name =name;
    if (!contex) {
        return NULL;
    }
    contex->queues=calloc(quneCount, sizeof(void*));
    if (!contex->queues) {
        free(contex);
    }
    if ([UIDevice currentDevice].systemVersion.floatValue>8.0) {
        dispatch_qos_class_t qos_class = NSQualityOfServiceToQOSClass(qos);
        dispatch_queue_attr_t att = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, qos_class, 0);
        for (int i=0; i<quneCount; i++) {
            dispatch_queue_t q = dispatch_queue_create(name, att);
            contex->queues[i]=(__bridge_retained  void*)q;
        }
        
    }else{
        for (int i=0; i<quneCount; i++) {
            long identifier = NSQualityOfServiceToDispatchPriority(qos);
            dispatch_queue_t q =  dispatch_queue_create(name, DISPATCH_QUEUE_SERIAL);
            dispatch_set_target_queue(q, dispatch_get_global_queue(identifier, 0));
            contex->queues[i] =(__bridge_retained void*)q;
        }
        
    }
    
    return contex;
}

4、根據(jù)不同的優(yōu)先級(jí)創(chuàng)建隊(duì)列組乍楚。其中用到了單例模式当编,實(shí)現(xiàn)全局的獲取,避免多次創(chuàng)建徒溪。

static LHDispatchContext* LHDispatchGetContexforQos(NSQualityOfService qos){
    static LHDispatchContext* contexArr[5]={0};//創(chuàng)建一個(gè)LHDispatchContext數(shù)組用與存儲(chǔ)不同優(yōu)先級(jí)下的contex忿偷。
    switch (qos) {
        case NSQualityOfServiceUserInteractive:{
            static dispatch_once_t onceToken;
            dispatch_once(&onceToken, ^{
                 int count = (int)[NSProcessInfo processInfo].activeProcessorCount;
                count = count<1?1:count>MaxQueueCount?MaxQueueCount:count;
                contexArr[0] = LHDispatchCreatQueue("com.lh.pool-user-Interactive", count, qos);
            });
            return contexArr[0];
        }break;

        case NSQualityOfServiceUserInitiated: {
            static dispatch_once_t onceToken;
            dispatch_once(&onceToken, ^{
                int count = (int)[NSProcessInfo processInfo].activeProcessorCount;
                count = count<1?1:count>MaxQueueCount?MaxQueueCount:count;//取當(dāng)前活躍的進(jìn)程數(shù),創(chuàng)建串行隊(duì)列數(shù)組词渤,以達(dá)到資源的合理利用牵舱。
                contexArr[1] = LHDispatchCreatQueue("com.lh.pool-user-Initiated", count, qos);
            });
            return contexArr[1];
            break;
        }
        case NSQualityOfServiceUtility: {
            static dispatch_once_t onceToken;
            dispatch_once(&onceToken, ^{
                int count = (int)[NSProcessInfo processInfo].activeProcessorCount;
                count = count<1?1:count>MaxQueueCount?MaxQueueCount:count;
                contexArr[2] = LHDispatchCreatQueue("com.lh.pool-user-Utility", count, qos);
            });
            return contexArr[2];
            break;
        }
        case NSQualityOfServiceBackground: {
            static dispatch_once_t onceToken;
            dispatch_once(&onceToken, ^{
                int count = (int)[NSProcessInfo processInfo].activeProcessorCount;
                count = count<1?1:count>MaxQueueCount?MaxQueueCount:count;
                contexArr[3] = LHDispatchCreatQueue("com.lh.pool-user-Background", count, qos);
            });
            return contexArr[3];
            break;
        }
        case NSQualityOfServiceDefault: {
            static dispatch_once_t onceToken;
            dispatch_once(&onceToken, ^{
                int count = (int)[NSProcessInfo processInfo].activeProcessorCount;
                count = count<1?1:count>MaxQueueCount?MaxQueueCount:count;
                contexArr[4] = LHDispatchCreatQueue("com.lh.pool-user-Default", count, qos);
            });
            return contexArr[4];
            break;
        }
    }
    return NULL;
}

最后總結(jié):

  • YYLabel 可以用來(lái)實(shí)現(xiàn)異步渲染。
  • 當(dāng)改變了 Frame缺虐、更新了 UIView/CALayer 的層次時(shí)芜壁,或者手動(dòng)調(diào)用了 UIView/CALayer 的 setNeedsLayout/setNeedsDisplay方法后,這個(gè) UIView/CALayer 就被標(biāo)記為待處理高氮,并被提交到一個(gè)全局的容器去
  • 由于runloop會(huì)在即將進(jìn)入休眠或者退出時(shí)處理所有被標(biāo)記過(guò)的UIView/CALayer慧妄,通過(guò)調(diào)用drawrect/display完成渲染。
  • N個(gè)串行隊(duì)列相當(dāng)于N個(gè)一條生產(chǎn)線的渲染工廠剪芍,我按順序把任務(wù)分配給各個(gè)工廠塞淹,非常井井有條的一種生產(chǎn)分配方式??。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末罪裹,一起剝皮案震驚了整個(gè)濱河市饱普,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌状共,老刑警劉巖套耕,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異峡继,居然都是意外死亡冯袍,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)康愤,“玉大人儡循,你說(shuō)我怎么就攤上這事≌骼洌” “怎么了择膝?”我有些...
    開封第一講書人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)资盅。 經(jīng)常有香客問(wèn)我调榄,道長(zhǎng),這世上最難降的妖魔是什么呵扛? 我笑而不...
    開封第一講書人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮筐带,結(jié)果婚禮上今穿,老公的妹妹穿的比我還像新娘。我一直安慰自己伦籍,他們只是感情好蓝晒,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著帖鸦,像睡著了一般芝薇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上作儿,一...
    開封第一講書人閱讀 49,950評(píng)論 1 291
  • 那天洛二,我揣著相機(jī)與錄音,去河邊找鬼攻锰。 笑死晾嘶,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的娶吞。 我是一名探鬼主播垒迂,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼妒蛇!你這毒婦竟也來(lái)了机断?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤绣夺,失蹤者是張志新(化名)和其女友劉穎吏奸,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體乐导,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡苦丁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了物臂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片旺拉。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡产上,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蛾狗,到底是詐尸還是另有隱情晋涣,我是刑警寧澤,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布沉桌,位于F島的核電站谢鹊,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏留凭。R本人自食惡果不足惜佃扼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蔼夜。 院中可真熱鬧兼耀,春花似錦、人聲如沸求冷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)匠题。三九已至拯坟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間韭山,已是汗流浹背郁季。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留掠哥,地道東北人巩踏。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像续搀,于是被迫代替她去往敵國(guó)和親塞琼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容

  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時(shí)...
    歐辰_OSR閱讀 29,340評(píng)論 8 265
  • OC語(yǔ)言基礎(chǔ) 1.類與對(duì)象 類方法 OC的類方法只有2種:靜態(tài)方法和實(shí)例方法兩種 在OC中禁舷,只要方法聲明在@int...
    奇異果好補(bǔ)閱讀 4,259評(píng)論 0 11
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,093評(píng)論 1 32
  • 1彪杉、通過(guò)CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫(kù)組件 SD...
    陽(yáng)明先生_X自主閱讀 15,969評(píng)論 3 119
  • 趕在燈會(huì)結(jié)束的最后一天,再次來(lái)豫園看燈會(huì)牵咙。這是豫園的傳統(tǒng)節(jié)目派近,在這里似乎能感受到上海的年味〗嘧溃看完燈會(huì)渴丸,感覺(jué)這個(gè)新年...
    張小末閱讀 417評(píng)論 0 0