GCD基礎(chǔ)知識集合

GCD概念簡單理解

GCD是基于C的Api。不需要自己管理線程生死。只需要創(chuàng)建隊列,把任務(wù)放進隊列里面就可以了。看上去很簡單,其實也是有一段心酸路。
GCD有兩個核心概念。一個是任務(wù),一個是隊列。

同步函數(shù):在當前線程中執(zhí)行,不開啟新的線程
dispatch_sync(dispatch_queue_t queue, dispatch_block_tblock);

異步函數(shù):具備開啟線程的能力。
dispatch_async(dispatch_queue_t queue, dispatch_block_tblock);

隊列

并發(fā)隊列
自動開啟多個線程,并且可以讓多個任務(wù)同時執(zhí)行。
僅僅在異步函數(shù)(dispatch_async)下有效。

串行隊列
讓線程一個接著一個的執(zhí)行。一條線程執(zhí)行完后再執(zhí)行下一條線程。

并發(fā)隊列

并發(fā)隊列不需要手動創(chuàng)建。以下是創(chuàng)建代碼。

dispatch_queue_tdispatch_get_global_queue(
dispatch_queue_priority_tpriority,// 隊列的優(yōu)先級
unsignedlongflags);// 此參數(shù)暫時無用,用0即可
dispatch_queue_tqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//獲得全局并發(fā)隊列

全局并發(fā)隊列的優(yōu)先級
#defineDISPATCH_QUEUE_PRIORITY_HIGH 2 // 高
#defineDISPATCH_QUEUE_PRIORITY_DEFAULT 0 // 默認(中)
#defineDISPATCH_QUEUE_PRIORITY_LOW (-2)// 低
#defineDISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 后臺
串行隊列
使用dispatch_queue_create函數(shù)創(chuàng)建串行隊列
dispatch_queue_t
dispatch_queue_create(constchar*label, //隊列名稱
dispatch_queue_attr_tattr);//隊列屬性,一般用NULL即可
dispatch_queue_tqueue = dispatch_queue_create("isQueue", NULL);//創(chuàng)建
dispatch_release(queue);//非ARC時候需要釋放手動創(chuàng)建的隊列

使用主隊列(跟主線程相關(guān)聯(lián)的隊列)
主隊列是GCD自帶的一種特殊的串行隊列
放在主隊列中的任務(wù),都會放到主線程中執(zhí)行
使用dispatch_get_main_queue()獲得主隊列
dispatch_queue_tqueue = dispatch_get_main_queue();

使用dispatch_sync同步函數(shù)時候,在主線程中往主隊列添加任務(wù)會造成死鎖。

隊列與任務(wù)的結(jié)合
函數(shù) 全局并發(fā)隊列 手動創(chuàng)建串行隊列 主隊列
同步 (sync) 沒有開啟新線程 串行執(zhí)行任務(wù) 沒有開啟新線程 串行執(zhí)行任務(wù) 沒有開啟新線程 串行執(zhí)行任務(wù)
異步 (async) 有開啟新線程 并發(fā)執(zhí)行任務(wù) 有開啟新線程 串行執(zhí)行任務(wù) 沒有開啟新線程 串行執(zhí)行任務(wù)
線程間的通訊

更新UI,數(shù)據(jù)等都是要回到主線程的。不能在子線程。

//獲取全局隊列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^{

        NSLog(@"-子線程-- 開始下載圖片--%@",[NSThread currentThread]);

        //下載數(shù)據(jù)是耗時操作放到子線程
        UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://b.hiphotos.baidu.com/image/pic/item/b219ebc4b74543a94369f4cb1c178a82b9011442.jpg"]]];

            dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"-主線程-- 刷新UI--%@",[NSThread currentThread]);
            //回到主線程刷新UI
            self.imageView.image = image;
        });
    });
延時操作

延時操作不會堵塞當前線程.

//延遲操作
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(<#delayInSeconds#> * NSEC_PER_SEC)),//從什么時候開始,是一個固定的算法
                   dispatch_get_main_queue(),//隊列
                   ^{
        //做要做的操作
    });
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

#pragma mark 延遲操作創(chuàng)建一
    //獲取全局隊列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    //延時多久
    dispatch_time_t whenTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
    
    //延時操作,根據(jù)whenTime設(shè)計的時間
    dispatch_after(whenTime, queue, ^{
        NSLog(@"倒計時結(jié)束");
        
        dispatch_async(queue, ^{
            NSLog(@"-子線程-- 開始下載圖片--%@",[NSThread currentThread]);
            
            //下載數(shù)據(jù)是耗時操作放到子線程
            UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://b.hiphotos.baidu.com/image/pic/item/b219ebc4b74543a94369f4cb1c178a82b9011442.jpg"]]];
            
            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"-主線程-- 刷新UI--%@",[NSThread currentThread]);
                
                //回到主線程刷新UI
                self.imageView.image = image;
                
            });
        });
    });
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    
#pragma mark 延遲操作創(chuàng)建二
    //獲取全局隊列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        
        NSLog(@"倒計時結(jié)束");
        
        dispatch_async(queue, ^{
            NSLog(@"-子線程-- 開始下載圖片--%@",[NSThread currentThread]);
            
            //下載數(shù)據(jù)是耗時操作放到子線程
            UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://b.hiphotos.baidu.com/image/pic/item/b219ebc4b74543a94369f4cb1c178a82b9011442.jpg"]]];
            
            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"-主線程-- 刷新UI--%@",[NSThread currentThread]);
                
                //回到主線程刷新UI
                self.imageView.image = image;
            });
        });
    });
GCD一次性代碼
static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
            //代碼只執(zhí)行一次
    });
});
GCD隊列組
分組模式 dispatch_group_notify

可以異步執(zhí)行多個耗時操作。等耗時操作都執(zhí)行完畢之后會回到主線程執(zhí)行操作。主要用于監(jiān)聽任務(wù)是否完成。

//獲取全局隊列
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //創(chuàng)建一個隊列組
    dispatch_group_t group = dispatch_group_create();
    
    dispatch_group_async(group, globalQueue, ^{
        
        NSLog(@"--- 1 開始--- %@",[NSThread currentThread]);
        //延時5秒 模仿堵塞子線程
        [NSThread sleepForTimeInterval:5];
        NSLog(@"--- 2 --- 完成 %@",[NSThread currentThread]);
        
    });
    
    dispatch_group_async(group, globalQueue, ^{

        NSLog(@"--- 2 開始--- %@",[NSThread currentThread]);
        //延時5秒 模仿堵塞子線程
        [NSThread sleepForTimeInterval:5];
        NSLog(@"--- 2 --- 完成 %@",[NSThread currentThread]);
        
    });
    
    //在這個隊列組里面,會等group中的全部代碼執(zhí)行完畢再去執(zhí)行其它的操作
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        
        // 等前面的異步操作都執(zhí)行完畢后,回到主線程...
        NSLog(@"全部完成");
        
    });

    //非ARC時候要釋放掉
    //dispatch_release(group);
dispatch_apply組內(nèi)無序循環(huán)執(zhí)行任務(wù)
//循環(huán)執(zhí)行任務(wù),并且執(zhí)行任務(wù)的順序是無序列的。這里會堵塞當前的線程。所以要注意。一般都是在子線程中執(zhí)行。
dispatch_apply(size_t iterations,//執(zhí)行的次數(shù)
                   <#dispatch_queue_t queue#>,//隊列
                   <#^(size_t)block#>)//任務(wù)
    dispatch_apply(5, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t index) {
        NSLog(@"%zu",index);
    });
dispatch_set_target_queue 變更queue的優(yōu)先級別
dispatch_queue_t exampleQueue = dispatch_queue_create("com.example.queue", NULL);
    //設(shè)置這個全局并發(fā)隊列的優(yōu)先級為后臺
    dispatch_queue_t globalQueued = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
    dispatch_set_target_queue(exampleQueue, globalQueued);
    /**
     *  經(jīng)過轉(zhuǎn)換之后exampleQueue的優(yōu)先級別變成后臺
     */
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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