GCD

兩個(gè)特殊隊(duì)列:

dispatch_get_main_queue()主隊(duì)列,串行隊(duì)列。
dispatch_get_global_queue(0, 0)全局并發(fā)隊(duì)列。這個(gè)隊(duì)列是系統(tǒng)維護(hù)的,會(huì)被用來(lái)處理很多系統(tǒng)級(jí)事件。

最簡(jiǎn)單的block:

dispatch_block_t這是個(gè)無(wú)參無(wú)返回值的block。

關(guān)于同步異步函數(shù):

dispatch_sync同步函數(shù)沒(méi)有開(kāi)啟線程的能力。所有的代碼都會(huì)在當(dāng)前線程立即執(zhí)行。
dispatch_async異步函數(shù)有開(kāi)啟線程的能力。

關(guān)于串行并行隊(duì)列:

dispatch_queue_create(0,0)
DISPATCH_CURRENT_QUEUE_LABEL串行隊(duì)列遵循FIFO原則,先進(jìn)先出。
DISPATCH_QUEUE_CONCURRENT并行隊(duì)列,之間不會(huì)相互影響會(huì)各自執(zhí)行。執(zhí)行順序與加入隊(duì)列順序有關(guān)。
排列組合之后,就有了這么一套機(jī)制,如下圖:

image.png

知識(shí)點(diǎn)較多的主要是同步函數(shù)串行隊(duì)列。產(chǎn)生堵塞的原因本質(zhì)上還是任務(wù)執(zhí)行順序的問(wèn)題。如下經(jīng)典代碼就會(huì)產(chǎn)生堵塞(死鎖):

 // 同步隊(duì)列
    dispatch_queue_t queue = dispatch_queue_create("xxx", DISPATCH_QUEUE_SERIAL);
    NSLog(@"1");
    // 異步函數(shù)
    dispatch_async(queue, ^{
        NSLog(@"2");
        // 同步
        dispatch_sync(queue, ^{
             NSLog(@"3");
        });
          NSLog(@"4");
    });
    NSLog(@"5");

分析圖如下


image.png

本質(zhì)上,異步函數(shù)里的代碼是加入隊(duì)列后,按順序執(zhí)行的。所以會(huì)執(zhí)行2->同步->4
但是,同步函數(shù)的性質(zhì)又會(huì)讓代碼立即執(zhí)行。所以在執(zhí)行同步函數(shù)的時(shí)候,會(huì)要求立即執(zhí)行log3。
但是log3這個(gè)任務(wù)因?yàn)榇嘘?duì)列順序的原因,必須等到log4執(zhí)行完畢之后才會(huì)執(zhí)行。
此時(shí)發(fā)生了log4log3相互等待的情況,而產(chǎn)生了堵塞。

這只是同步串行會(huì)出現(xiàn)問(wèn)題的一種方式。單純的在主線程中使用同步串行,是沒(méi)有問(wèn)題,而且借助其一定會(huì)按順序執(zhí)行的特性。還能達(dá)到某些鎖的功能:如經(jīng)典的購(gòu)票問(wèn)題:

- (void)saleTickes {
    self.tickets = 20;
    _queue = dispatch_queue_create("xxx", DISPATCH_QUEUE_SERIAL);
    while (self.tickets > 0) {
        // 使用串行隊(duì)列,同步任務(wù)賣(mài)票
        dispatch_sync(_queue, ^{
            // 檢查票數(shù)
            if (self.tickets > 0) {
                self.tickets--;
            }
        });
    }
}

代碼很簡(jiǎn)單,不需要解釋。這個(gè)demo只是說(shuō)明同步串行的效果。其實(shí)這段代碼意義不大,因?yàn)閷?shí)現(xiàn)購(gòu)票必定要在異步并發(fā)隊(duì)列里才會(huì)更好的達(dá)到效果。如下:

- (void)saleTickes {
    NSLock *lock = [NSLock new];
    _tickets = 20;
    _queue = dispatch_queue_create("Cooci", DISPATCH_QUEUE_CONCURRENT);
    while (self.tickets > 0) {
        [lock lock];
        dispatch_async(_queue, ^{
            // 檢查票數(shù)
            if (self.tickets > 0) {
                self.tickets--;
                NSLog(@"還剩 %zd %@", self.tickets, [NSThread currentThread]);
            } else {
                NSLog(@"沒(méi)有票了");
            }
            [lock unlock];
        });
    }
}

柵欄函數(shù):

柵欄函數(shù)的用法,多用于控制并發(fā)隊(duì)列的執(zhí)行時(shí)機(jī),并且只用于控制唯一一個(gè)并發(fā)隊(duì)列(控制串行隊(duì)列沒(méi)有意義)。其中的barrier單詞很好的說(shuō)明了他的作用。就是個(gè)擋路的:在我之前的任務(wù)都要被我擋住,等我執(zhí)行完畢之后,之后的任務(wù)才會(huì)執(zhí)行。
dispatch_barrier_sync同步柵欄函數(shù):不僅僅會(huì)阻擋 并發(fā)隊(duì)列的任務(wù),還會(huì)阻擋 當(dāng)前線程的任務(wù) 。直至該函數(shù) 之前的并發(fā)隊(duì)列任務(wù) 執(zhí)行完畢后,才會(huì)繼續(xù)執(zhí)行 當(dāng)前線程的任務(wù)后面的并發(fā)任務(wù)
dispatch_barrier_async異步柵欄函數(shù):只阻擋 并發(fā)隊(duì)列的任務(wù) 。不會(huì)阻擋 當(dāng)前線程的任務(wù) 。所以 當(dāng)前線程的任務(wù) ,都會(huì)比 所有的并發(fā)隊(duì)列的任務(wù) 先執(zhí)行。
demo如下:就不解釋了

- (void)demo2{
    dispatch_queue_t concurrentQueue = dispatch_queue_create("cooci", DISPATCH_QUEUE_CONCURRENT);
    /* 1.異步函數(shù) */
    dispatch_async(concurrentQueue, ^{
        for (NSUInteger i = 0; i < 5; i++) {
            NSLog(@"download1-%zd-%@",i,[NSThread currentThread]);
        }
    });
    
    dispatch_async(concurrentQueue, ^{
        for (NSUInteger i = 0; i < 5; i++) {
            NSLog(@"download2-%zd-%@",i,[NSThread currentThread]);
        }
    });
    
    /* 2. 柵欄函數(shù) */
    dispatch_barrier_sync(concurrentQueue, ^{
        NSLog(@"---------------------%@------------------------",[NSThread currentThread]);
    });
    NSLog(@"加載那么多,喘口氣!!!");
    /* 3. 異步函數(shù) */
    dispatch_async(concurrentQueue, ^{
        for (NSUInteger i = 0; i < 5; i++) {
            NSLog(@"日常處理3-%zd-%@",i,[NSThread currentThread]);
        }
    });
    NSLog(@"**********起來(lái)干!!");
    
    dispatch_async(concurrentQueue, ^{
        for (NSUInteger i = 0; i < 5; i++) {
            NSLog(@"日常處理4-%zd-%@",i,[NSThread currentThread]);
        }
    });
}

調(diào)度組:

用這個(gè)也可以控制任務(wù)調(diào)度順序。用法如下:

 - (void)groupDemo {
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_group_t group = dispatch_group_create();
    
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        NSLog(@"第一個(gè)走完了");
        dispatch_group_leave(group);
    });
    
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        NSLog(@"第二個(gè)走完了");
        dispatch_group_leave(group);
    });
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"所有任務(wù)完成,可以更新UI");
        
    });
}

注意:
1.dispatch_group_enterdispatch_group_leave需要成對(duì)出現(xiàn)。
2.dispatch_group_enter 多于 dispatch_group_leave 不會(huì)調(diào)用通知
3.dispatch_group_enter 少于 dispatch_group_leave 會(huì)奔潰
4.所有的dispatch_group_enter都要在dispatch_group_notify之前執(zhí)行。

?著作權(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)容

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