輕松學(xué)iOS多線程之 GCD 的常用函數(shù)

關(guān)于 iOS 多線程中 GCD 的基礎(chǔ)知識(shí)已在上一篇文章中詳細(xì)說(shuō)明,請(qǐng)參看《輕松學(xué)iOS多線程之 GCD 的基本使用》進(jìn)行了解,本文主要對(duì) GCD 中的幾種常用函數(shù)做進(jìn)一步概述。

在 GCD 中的常用函數(shù)主要有柵欄函數(shù)、一次性函數(shù)、延遲執(zhí)行函數(shù)、快速迭代函數(shù),最后包括 隊(duì)列組的使用以及線程間的通信。

一、柵欄函數(shù)

柵欄函數(shù)的作用是用來(lái)控制任務(wù)的執(zhí)行順序,必須上面的任務(wù) 1 執(zhí)行完畢才執(zhí)行當(dāng)前柵欄任務(wù),必須當(dāng)前柵欄任務(wù)執(zhí)行完畢才執(zhí)行下面的任務(wù) 2。

//1.獲取并發(fā)隊(duì)列 
dispatch_queue_t queue = dispatch_queue_create("barrier", DISPATCH_QUEUE_CONCURRENT);
    //2.異步函數(shù)
dispatch_async(queue, ^{
    NSLog(@"1 --- %@", [NSThread currentThread]);
});
    //3.設(shè)置柵欄
dispatch_barrier_async(queue, ^{
    NSLog(@" ++++++++++++++ ");
});
dispatch_async(queue, ^{
    NSLog(@"2 --- %@", [NSThread currentThread]);
});

注意:柵欄函數(shù)不能使用全局并發(fā)隊(duì)列,會(huì)喪失攔截功能

二、一次性函數(shù)

一次性函數(shù)顧名思義就是在程序的運(yùn)行過(guò)程中,一次性函數(shù)中的代碼只會(huì)執(zhí)行一次,一次性函數(shù)的內(nèi)部原理就是開(kāi)始時(shí) onceToken == 0,如果為 0 則執(zhí)行,執(zhí)行之后值為 -1,就不執(zhí)行了。一次性函數(shù)在單例中會(huì)經(jīng)常使用。

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    NSLog(@"只執(zhí)行一次,默認(rèn)是線程安全的");
});

注意:一次性函數(shù)不能放入懶加載中

三、延遲執(zhí)行函數(shù)

在以往的學(xué)習(xí)中,我們已經(jīng)知道了兩種實(shí)現(xiàn)延時(shí)執(zhí)行的方法:

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

在 GCD 中利用 dispatch_after 也可以實(shí)現(xiàn)延遲執(zhí)行的效果:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    NSLog(@"延時(shí) 2.0 秒執(zhí)行");
});

在延遲執(zhí)行中,dispatch_after 函數(shù)本身是一個(gè)異步函數(shù),其中的隊(duì)列也可以使用自定義的隊(duì)列,它的實(shí)質(zhì)是延遲 2 秒再將任務(wù)提交到隊(duì)列中,從而達(dá)到延遲執(zhí)行的效果。

四、快速迭代函數(shù)(遍歷)

在以往我們知道可以使用 for 循環(huán)和 block 進(jìn)行遍歷,在 GCD 中我們也可以使用 dispatch_apply 函數(shù)進(jìn)行快速迭代。

dispatch_queue_t queue = dispatch_get_global_queue(0, 0);  
dispatch_apply(10, queue, ^(size_t i) {
    NSLog(@"%zd --- %@", i, [NSThread currentThread]);
});

在 dispatch_apply 函數(shù)中的三個(gè)參數(shù)分別代表著需要遍歷的次數(shù),存放任務(wù)的隊(duì)列以及索引(就相當(dāng)于 for 循環(huán)中的 i )。

注意:1. 快速迭代中的隊(duì)列只能使用并發(fā)隊(duì)列,不要使用串行隊(duì)列或主隊(duì)列,使用串行隊(duì)列時(shí)就相當(dāng)于 for 循環(huán),使用主隊(duì)列會(huì)造成死鎖。

2. 在快速迭代中,會(huì)開(kāi)啟子線程與主線程一起并發(fā)執(zhí)行任務(wù),執(zhí)行順序是不固定的。

五、隊(duì)列組的基本使用

需求:同時(shí)下載圖片一和圖片二,當(dāng)兩張圖片均下載完畢后合成使之成為一張圖片。

在以前我們可以利用 GCD 中的柵欄函數(shù)解決這個(gè)問(wèn)題,具體的思路為:使用異步函數(shù) + 并發(fā)隊(duì)列開(kāi)啟子線程來(lái)同時(shí)下載圖片,然后添加一個(gè)柵欄函數(shù)進(jìn)行攔截,最后在柵欄函數(shù)之后進(jìn)行合成圖片的任務(wù),這里需要注意的是在合成圖片的子線程中需要回到主線程(異步函數(shù) + 主隊(duì)列)進(jìn)行展示圖片。

其實(shí)除此之外,我們也可以利用隊(duì)列組來(lái)解決這個(gè)問(wèn)題,當(dāng)隊(duì)列組中所有的任務(wù)都執(zhí)行完畢,就會(huì)執(zhí)行 dispatch_group_notify 函數(shù)。

//創(chuàng)建隊(duì)列組
dispatch_group_t group = dispatch_group_create();
//創(chuàng)建并發(fā)隊(duì)列
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
//將任務(wù)添加到隊(duì)列組中
dispatch_group_async(group, queue, ^{
    NSLog(@"1 --- %@", [NSThread currentThread]);
});
//該函數(shù)本身是異步函數(shù)
dispatch_group_notify(group, queue, ^{
    NSLog(@"--- end --- %@", [NSThread currentThread]);
});

六、線程間的通信

在子線程中下載圖片回到主線程設(shè)置并顯示:

//1.獲取隊(duì)列(串行|并行) 0 就是異步函數(shù)
dispatch_queue_t queue = dispatch_queue_create(0, 0);
//2.異步函數(shù)封裝任務(wù)提交到隊(duì)列
dispatch_async(queue, ^{       
    //3.獲取 URL
    NSURL *url = [NSURL URLWithString:@"http://c.hiphotos.baidu.com/image/pic/item/3b292df5e0fe99254674c15036a85edf8db171b2.jpg"];
    //4.下載二進(jìn)制數(shù)據(jù)
    NSData *imageData = [NSData dataWithContentsOfURL:url];
    //5.將二進(jìn)制數(shù)據(jù)轉(zhuǎn)換為圖片
    UIImage *image = [UIImage imageWithData:imageData];
    //6.回到主線程設(shè)置圖片(異步函數(shù) + 主隊(duì)列)
    dispatch_async(dispatch_get_main_queue(), ^{
        self.imageView.image = image;
        NSLog(@"%@", [NSThread currentThread]);
    });
});
最后編輯于
?著作權(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)容

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