iOS GCD的使用

本文的主要內(nèi)容是:

  1. 什么是GCD
  2. 了解GCD前,需要了解的基礎(chǔ)知識
  3. GCD的使用
  4. 使用注意事項

-GCD學(xué)習(xí)前鋪墊-

什么是GCD

  1. GCD (Grand Central Dispatch) 是Apple公司開發(fā)的一種技術(shù),它旨在優(yōu)化多核環(huán)境中的并發(fā)操作并取代傳統(tǒng)多線程的編程模式
  2. GCD是基于C語言的線程管理方案,使用者無需過多參與線程的管理,只需要將想要執(zhí)行的代碼,添加到想要添加的調(diào)度隊列即可
  3. 在Mac OS X 10.6雪豹中首次推出,并在iOS4.0中引入到了iOS
  4. GCD主要用在后臺執(zhí)行較慢任務(wù);延遲執(zhí)行任務(wù);以及在后臺任務(wù)中,切換回主線程,更新UI

iOS中常用的其它多線程技術(shù)

pthread:通用于Unix/Linux/Windows的C語言線程管理API,可移植性強(qiáng),但是使用繁瑣,需要使用者管理線程生命周期

NSThread:使用Objective-C實現(xiàn),輕量級的線程管理,但是也需要手動管理線程的生命周期

NSOperation:基于GCD,使用Objective-C實現(xiàn)的面向?qū)ο蟮木€程管理,比GCD更高級,但是處理簡單任務(wù)會比GCD代碼更多

總之,iOS里GCD用的很多

GCD知識鋪墊

競爭&同步:兩個線程搶奪同一個資源,就會競爭,為了防止競爭,一個線程擁有資源的時候,會對資源加鎖,另一個線程就要等待解鎖以后再擁有這個資源,這叫同步。

死鎖:兩個線程互相等待對方釋放資源

主線程&后臺線程:主線程也叫前臺線程,程序啟動的默認(rèn)線程,操作UI的線程。后臺線程,即非主線程,用于不影響主線程的完成一些任務(wù)

并行&串行:并行,就是幾個任務(wù)一起完成。串行,就是幾個任務(wù)一個接著一個完成。

同步&異步:同步執(zhí)行線程,等待新線程執(zhí)行完以后,再繼續(xù)執(zhí)行當(dāng)前線程,很少用到。異步執(zhí)行線程,在執(zhí)行新線程的同時,繼續(xù)執(zhí)行當(dāng)前線程,常用。

-GCD的使用-

GCD的使用步驟

  1. 創(chuàng)建線程隊列:主隊列,全局并行隊列,手動創(chuàng)建串行隊列
  2. 選擇執(zhí)行方式:同步(較少使用),異步,延時
  3. 添加需要執(zhí)行的任務(wù):也就是想要創(chuàng)建隊列做什么,以Block塊語句形式創(chuàng)建
  4. 任務(wù)被執(zhí)行:Block按照設(shè)計被執(zhí)行

舉例

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"我在五秒后打印");
    });
    NSLog(@"線程被部署");

這段代碼的原型如下

void dispatch_after(dispatch_time_t when,
    dispatch_queue_t queue,
    dispatch_block_t block);
  1. 首先,創(chuàng)建線程隊列,本例中我們使用主隊列,所以直接使用dispatch_get_main_queue()
  2. 然后,選擇執(zhí)行方式,本例使用延時方法dispatch_after
  3. 添加需要執(zhí)行的任務(wù),我們打印了一下log
    4.任務(wù)被執(zhí)行:
log

異步執(zhí)行線程

異步后臺線程

主要用途:執(zhí)行較慢的任務(wù),例如大量計算,網(wǎng)絡(luò)請求等

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"在異步并行隊列中執(zhí)行");
    });
    


    dispatch_queue_t queue = dispatch_queue_create("com.realank.GCDDemo.myQueue", NULL);
    dispatch_async(queue, ^{
        NSLog(@"在異步串行隊列中執(zhí)行");
    });

上面的代碼,分別創(chuàng)建了一個異步后臺并行線程和一個自創(chuàng)建的異步后臺串行線程。

異步主線程

主要用途:用于在后臺線程的任務(wù)將要完成時,切換到主線程更新UI

    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"在異步主線程中執(zhí)行");
    });

同步執(zhí)行線程

同步后臺線程

主要用途:在新線程中執(zhí)行任務(wù),并且等待線程執(zhí)行完畢再向后執(zhí)行,幾乎不用

    dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"在同步并行隊列中執(zhí)行");
    });



    dispatch_queue_t queue = dispatch_queue_create("com.realank.GCDDemo.myQueue", NULL);
    dispatch_sync(queue, ^{
        NSLog(@"在同步串行隊列中執(zhí)行");
    });

上面的代碼,分別創(chuàng)建了一個異步后臺并行線程和一個自創(chuàng)建的異步后臺串行線程。

同步主線程(慎用)

主要用途:只有在其它線程中才可能執(zhí)行此方法,否則會死鎖

    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@“在同步主線程中執(zhí)行,慎用,否則會死鎖”);
    });

延時執(zhí)行線程

主要用途:用于等待一段時間以后再執(zhí)行的任務(wù)

    dispatch_queue_t queue = dispatch_get_main_queue();
//  也可以使用其它線程
//  dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//  dispatch_queue_t queue = dispatch_queue_create("com.realank.GCDDemo.myQueue2", NULL);
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), queue, ^{
        NSLog(@"延時2秒執(zhí)行");
    });
    NSLog(@"延時線程已部署");

-GCD的總結(jié)-

創(chuàng)建線程隊列

主隊列:

dispatch_queue_t queue = dispatch_get_main_queue();

全局并行隊列:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

手動創(chuàng)建串行隊列:

dispatch_queue_t queue = dispatch_queue_create("com.realank.GCDDemo.myQueue", NULL);

線程執(zhí)行方式

異步:

void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

同步(慎用):

void dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);

延時:

void dispatch_after(dispatch_time_t when,
               dispatch_queue_t queue,
               dispatch_block_t block);

關(guān)于循環(huán)強(qiáng)引用

在block中使用self,或者使用屬性(會隱含調(diào)用self),會讓block持有其類實例,如果此時block,又被存儲為類實例的copy或strong屬性,就會造成循環(huán)強(qiáng)引用。
在GCD的block使用中,不會造成類實例對block的引用,但是為了以防萬一,我習(xí)慣在Block中統(tǒng)一使用weakSelf來引用屬性或方法。

     __weak __typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        weakSelf.string = @“hello";
    });
最后編輯于
?著作權(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)容