IOS多線程-GCD

GCD

什么是GCD

  • 全稱是Grand Central Dispatch,可譯為“強(qiáng)大的調(diào)度器”
    純C語言,提供了非常多強(qiáng)大的函數(shù)

GCD的優(yōu)勢(shì)

  • GCD是蘋果公司為多核的并行運(yùn)算提出的解決方案
  • GCD會(huì)自動(dòng)利用更多的CPU內(nèi)核(比如雙核、四核)
  • GCD會(huì)自動(dòng)管理線程的生命周期(創(chuàng)建線程、調(diào)度任務(wù)、銷毀線程)
  • 程序員只需要告訴GCD想要執(zhí)行什么任務(wù),不需要編寫任何線程管理代碼

GCD的核心概念

  • 任務(wù):想要做什么事情

  • 隊(duì)列:執(zhí)行任務(wù)的順序

  • 步驟:

    • 寫好自己想要執(zhí)行的任務(wù)
    • 放在隊(duì)列里等待執(zhí)行(FIFO,GCD會(huì)根據(jù)隊(duì)列的順序進(jìn)行自動(dòng)取出執(zhí)行,并且根據(jù)情況創(chuàng)建線程)

隊(duì)列的類型

  • 并發(fā)隊(duì)列
    • 隊(duì)列里的任務(wù)會(huì)自動(dòng)開啟多個(gè)線程并發(fā)執(zhí)行,但是需要異步函數(shù)的任務(wù)才有效
    • 隊(duì)列只是影響任務(wù)執(zhí)行的方式,實(shí)際上并不能決定是否開啟新的線程,僅僅是并發(fā)隊(duì)列允許多個(gè)線程同時(shí)運(yùn)行,而串行隊(duì)列只能是一個(gè)一個(gè)任務(wù)在同一線程執(zhí)行.
    • 如何創(chuàng)建并發(fā)隊(duì)列
//通過直接創(chuàng)建的方式創(chuàng)建,參數(shù)決定是否是并發(fā)隊(duì)列
//DISPATCH_QUEUE_CONCURRENT代表并發(fā)隊(duì)列
//DISPATCH_QUEUE_SERIAL或NULL代表串行隊(duì)列
//標(biāo)示符代表這個(gè)隊(duì)列的一個(gè)標(biāo)記
dispatch_queue_t queue = dispatch_queue_create("標(biāo)示符", DISPATCH_QUEUE_CONCURRENT);

//通過獲取全局隊(duì)列來獲得一個(gè)并發(fā)隊(duì)列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//這兩個(gè)參數(shù),第一個(gè)是優(yōu)先級(jí)一般用默認(rèn),第二個(gè)直接設(shè)為0 是一個(gè)保留標(biāo)記,實(shí)際作用不大
  • 串行隊(duì)列
    • 隊(duì)列里的任務(wù)會(huì)以串行的形式一個(gè)一個(gè)按順序執(zhí)行
    • 如何創(chuàng)建串行隊(duì)隊(duì)列
//直接創(chuàng)建
//DISPATCH_QUEUE_SERIAL或NULL代表串行隊(duì)列
dispatch_queue_t queue = dispatch_queue_create("標(biāo)示符", DISPATCH_QUEUE_SERIAL);
//獲得主隊(duì)列,也是一種串行隊(duì)列
dispatch_queue_t queue = dispatch_get_main_queue();
  • 同步函數(shù)與異步函數(shù)
  • 異步函數(shù)具有創(chuàng)建線程的能力,同步函數(shù)并沒有.
  • 同步函數(shù)如何創(chuàng)建
//queue代表你要放入的隊(duì)列
dispatch_sync(queue, ^{
        //在這里寫要執(zhí)行的代碼
    });
  • 異步函數(shù)如何創(chuàng)建
//queue代表你要放入的隊(duì)列
dispatch_async(queue, ^{
        //在這里寫要執(zhí)行的代碼
    });
  • 柵欄函數(shù)
//隔斷函數(shù),前面執(zhí)行完才會(huì)執(zhí)行這個(gè)函數(shù),這個(gè)函數(shù)執(zhí)行完才會(huì)執(zhí)行其他后面的函數(shù)
dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);
//全局并發(fā)情況下有問題

不同的隊(duì)列與函數(shù)的組合會(huì)有不同的效果

  • 并行隊(duì)列+異步函數(shù):創(chuàng)建新的線程,并行執(zhí)行任務(wù)
  • 并行隊(duì)列+同步函數(shù):沒有新的線程,串行執(zhí)行任務(wù)
  • 串行隊(duì)列+異步函數(shù):創(chuàng)建新的線程,串行執(zhí)行任務(wù)
  • 串行隊(duì)列+同步函數(shù):沒有新的線程,串行執(zhí)行任務(wù)
  • 主隊(duì)列+異步函數(shù):沒有新的線程,串行執(zhí)行任務(wù)
  • 主隊(duì)列+同步函數(shù):沒有新的線程,串行執(zhí)行任務(wù)

線程之間通信示例

  • 一個(gè)示例,簡(jiǎn)單的表示了如何在不同的隊(duì)列之間做事情
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //在這里寫上放在全局隊(duì)列的代碼
        dispatch_async(dispatch_get_main_queue(), ^{
            //寫在這里就是執(zhí)行主函數(shù)的代碼
        });
    });

IOS上常見的延時(shí)代碼

//調(diào)用NSObject的方法
[self performSelector:@selector(run) withObject:nil afterDelay:2.0];
// 2秒后再調(diào)用self的run方法

//使用GCD函數(shù)
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    // 2秒后執(zhí)行這里的代碼...
});

//使用NSTimer
[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(test) userInfo:nil repeats:NO];

Once代碼,在整個(gè)程序運(yùn)行時(shí)只執(zhí)行一次

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    // 只執(zhí)行1次的代碼(這里面默認(rèn)是線程安全的)
});

快速迭代代碼

dispatch_apply(10, dispatch_get_global_queue(0, 0), ^(size_t index){
    // 執(zhí)行10次代碼,index順序不確定
});

分組隊(duì)列

  • 當(dāng)需要對(duì)隊(duì)列分組時(shí),而且有先后執(zhí)行順序的需求的時(shí)候可以進(jìn)行組
//創(chuàng)建一個(gè)組組隊(duì)隊(duì)列
dispatch_group_t group =  dispatch_group_create();
//使用組隊(duì)列異步函數(shù),分別有組隊(duì)列,和隊(duì)列的參數(shù).
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // 執(zhí)行1個(gè)耗時(shí)的異步操作
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // 執(zhí)行1個(gè)耗時(shí)的異步操作
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    // 等前面的異步操作都執(zhí)行完畢后,回到主線程...
});

IOS中的單例模式

  • 單例模式的作用

    • 可以保證在程序運(yùn)行過程,一個(gè)類只有一個(gè)實(shí)例,而且該實(shí)例易于供外界訪問
    • 從而方便地控制了實(shí)例個(gè)數(shù),并節(jié)約系統(tǒng)資源
  • 單例模式的使用場(chǎng)合

    • 在整個(gè)應(yīng)用程序中,共享一份資源(這份資源只需要?jiǎng)?chuàng)建初始化1次)
  • 單例模式標(biāo)準(zhǔn)化代碼

  • 可以吧指針變?yōu)閕d類型,實(shí)例變量名定義為instance這樣就可以在多處使用了.

#import "Person.h"
@interface Person() <NSCopying>

@end

@implementation Person
//聲明一個(gè)全局變量指針,代表唯一的實(shí)例
static Person *_person;
//重寫alloc中實(shí)際起作用的部分,allocWihtZone,所以從始至終就只有一份存儲(chǔ)空間.
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
    //在程序整個(gè)生命過程中只運(yùn)行一次的代碼
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{

        _person = [super allocWithZone:zone];
    });
    return _person;
}

//生成一個(gè)完整的對(duì)象
+ (instancetype)shareWihtPerson
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _person = [[Person alloc] init];
    });
    return _person;
}

//防止使用copy拷貝出新的對(duì)象
- (id)copyWithZone:(NSZone *)zone
{
    return _person;
}

@end

最后編輯于
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 多線程學(xué)習(xí)筆記-GCD 我把這篇文章所用到的代碼總結(jié)到這里->GCD項(xiàng)目總結(jié)下載地址-GCD-wxk可以下載參考 ...
    wxkkkkk閱讀 569評(píng)論 0 2
  • 目錄:iOS多線程(一)--pthread、NSThreadiOS多線程(二)--GCD詳解iOS多線程(三)--...
    Claire_wu閱讀 1,136評(píng)論 0 6
  • 從哪說起呢? 單純講多線程編程真的不知道從哪下嘴。。 不如我直接引用一個(gè)最簡(jiǎn)單的問題,以這個(gè)作為切入點(diǎn)好了 在ma...
    Mr_Baymax閱讀 2,902評(píng)論 1 17
  • 前言 嘿嘿嘿,精品。 概述 全稱是Grand Central Dispatch,可譯為“牛逼的中樞調(diào)度器”。純C語...
    Ostkaka丶閱讀 1,160評(píng)論 0 12
  • 高中,人結(jié)束青少年,跨入成年的一個(gè)進(jìn)階。 高中三年是我們?nèi)松凶蠲篮玫臅r(shí)候,也是讓我們最難忘的。 屬于我們自己...
    0b1086b283cf閱讀 212評(píng)論 0 0

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