多線(xiàn)程 -- 多任務(wù)異步執(zhí)行完成后執(zhí)行刷新操作

在iOS開(kāi)發(fā)中我們經(jīng)常會(huì)遇到一起請(qǐng)求多個(gè)網(wǎng)絡(luò)數(shù)據(jù)的情況…但是有些操作卻是要在所有的網(wǎng)絡(luò)數(shù)據(jù)請(qǐng)求結(jié)束之后才可以進(jìn)行的….比如說(shuō)刷新控件收回.或者某些UI控件的更新..這種情況就不能單純的在某一條網(wǎng)絡(luò)請(qǐng)求結(jié)束后的block里操作了.一涉及到異步,GCD的強(qiáng)大之處就體現(xiàn)出來(lái)了..先上代碼:

*** 對(duì)列組與信號(hào)量 ***

 //信號(hào)量
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
//隊(duì)列組
dispatch_group_t group = dispatch_group_create();
//創(chuàng)建隊(duì)列 - 串行隊(duì)列與全局并發(fā)隊(duì)列擇一即可
// 使用串行隊(duì)列進(jìn)行網(wǎng)絡(luò)請(qǐng)求 -- 網(wǎng)絡(luò)請(qǐng)求的開(kāi)始無(wú)序,且在同一線(xiàn)程
dispatch_queue_t queue = dispatch_queue_create("www.baidu.com", DISPATCH_QUEUE_SERIAL);
// 使用并發(fā)隊(duì)列進(jìn)行網(wǎng)絡(luò)請(qǐng)求 -- 網(wǎng)絡(luò)請(qǐng)求的開(kāi)始無(wú)序,且線(xiàn)程不固定
queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//任務(wù)一
dispatch_group_async(group, queue, ^{
    // 無(wú)論成功或者失敗都要對(duì)信號(hào)量進(jìn)行標(biāo)記
    NSLog(@"此次請(qǐng)求線(xiàn)程是111111:%@",[NSThread currentThread]);
    [[AFHTTPSessionManager manager] POST:@"www.baidu.com" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        dispatch_semaphore_signal(semaphore);
        NSLog(@"success 此次返回的是111111 線(xiàn)程是:%@",[NSThread currentThread]);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        dispatch_semaphore_signal(semaphore);
        NSLog(@"failure 此次返回的是111111 線(xiàn)程是:%@",[NSThread currentThread]);
    }];
});
//任務(wù)二
dispatch_group_async(group, queue, ^{
    NSLog(@"此次請(qǐng)求線(xiàn)程是222222:%@",[NSThread currentThread]);
    [[AFHTTPSessionManager manager] POST:@"www.baidu.com" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        dispatch_semaphore_signal(semaphore);
        NSLog(@"success 此次返回的是222222 線(xiàn)程是:%@",[NSThread currentThread]);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        dispatch_semaphore_signal(semaphore);
        NSLog(@"failure 此次返回的是222222 線(xiàn)程是:%@",[NSThread currentThread]);
    }];
});

//任務(wù)三
dispatch_group_async(group, queue, ^{
    NSLog(@"此次請(qǐng)求線(xiàn)程是333333:%@",[NSThread currentThread]);
    [[AFHTTPSessionManager manager] POST:@"www.baidu.com" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        dispatch_semaphore_signal(semaphore);
        NSLog(@"success 此次返回的是333333 線(xiàn)程是:%@",[NSThread currentThread]);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        // 模擬網(wǎng)絡(luò)延遲
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            dispatch_semaphore_signal(semaphore);
            NSLog(@"failure 此次返回的是333333 線(xiàn)程是:%@",[NSThread currentThread]);
        });
    }];
});
// 所有網(wǎng)絡(luò)請(qǐng)求結(jié)束后會(huì)來(lái)到這個(gè)方法
dispatch_group_notify(group, queue, ^{
    //3個(gè)任務(wù),3個(gè)信號(hào)等待.
    // 這里信號(hào)等待需要與實(shí)際任務(wù)數(shù)相同 -- 若此處信號(hào)等待數(shù)量多于任務(wù)數(shù)(其實(shí)是任務(wù)成功或者失敗后標(biāo)記的信號(hào)量總數(shù)) 則后續(xù)代碼永遠(yuǎn)不會(huì)被執(zhí)行,若此處信號(hào)等待數(shù)量少于任務(wù)數(shù),則會(huì)提前執(zhí)行
    NSLog(@"當(dāng)前線(xiàn)程是:%@",[NSThread currentThread]);
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
//        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
//        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    //這里就是所有異步任務(wù)請(qǐng)求結(jié)束后執(zhí)行的代碼 -- UI操作需要回到主線(xiàn)程
    dispatch_async(dispatch_get_main_queue(), ^{
        // 刷新UI
        NSLog(@"主線(xiàn)程刷新UI  線(xiàn)程是:%@",[NSThread currentThread]);
    });
});

** ??在這里為何使用隊(duì)列組之后還要使用信號(hào)量-- 因?yàn)樵谶@里隊(duì)列組只能保證入組的任務(wù)執(zhí)行完畢,但是在入組后的異步操作,并不會(huì)等待,需要使用信號(hào)量等待 **

  1. 任務(wù)的成功與失敗回調(diào)中都必須標(biāo)記信號(hào)量 dispatch_semaphore_signal(semaphore);
  2. 信號(hào)等待時(shí)間和任務(wù)數(shù)必須一致
  3. 創(chuàng)建的隊(duì)列類(lèi)型不同會(huì)有稍微區(qū)別,代碼中給出了兩種,可自行選擇

真對(duì)信號(hào)量的情況幾種情況配圖:

隊(duì)列組- 信號(hào)量正常.png
信號(hào)等待量小于任務(wù)數(shù).png
信號(hào)等待量大于任務(wù)數(shù).png


*** 對(duì)列組方法2 ***

dispatch_group_t group = dispatch_group_create();
//創(chuàng)建隊(duì)列 - 串行隊(duì)列與全局并發(fā)隊(duì)列擇一即可
// 使用串行隊(duì)列進(jìn)行網(wǎng)絡(luò)請(qǐng)求 -- 網(wǎng)絡(luò)請(qǐng)求的開(kāi)始無(wú)序,且在同一線(xiàn)程
dispatch_queue_t queue = dispatch_queue_create("www.baidu.com", DISPATCH_QUEUE_SERIAL);
// 使用并發(fā)隊(duì)列進(jìn)行網(wǎng)絡(luò)請(qǐng)求 -- 網(wǎng)絡(luò)請(qǐng)求的開(kāi)始無(wú)序,且線(xiàn)程不固定
//    queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_group_enter(group);
dispatch_group_async(group, queue, ^{
    NSLog(@"此次請(qǐng)求線(xiàn)程是111111:%@",[NSThread currentThread]);
    // 網(wǎng)絡(luò)請(qǐng)求一
    [[AFHTTPSessionManager manager] POST:@"www.baidu.com" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        dispatch_group_leave(group);
        NSLog(@"success 此次返回的是111111 線(xiàn)程是:%@",[NSThread currentThread]);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        dispatch_group_leave(group);
        NSLog(@"failure 此次返回的是111111 線(xiàn)程是:%@",[NSThread currentThread]);
    }];
});
dispatch_group_enter(group);
dispatch_group_async(group, queue, ^{
    NSLog(@"此次請(qǐng)求線(xiàn)程是222222:%@",[NSThread currentThread]);
    // 網(wǎng)絡(luò)請(qǐng)求二
    [[AFHTTPSessionManager manager] POST:@"www.baidu.com" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        dispatch_group_leave(group);
        NSLog(@"success 此次返回的是222222 線(xiàn)程是:%@",[NSThread currentThread]);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        dispatch_group_leave(group);
        NSLog(@"failure 此次返回的是222222 線(xiàn)程是:%@",[NSThread currentThread]);
    }];
});
dispatch_group_enter(group);
dispatch_group_async(group, queue, ^{
    NSLog(@"此次請(qǐng)求線(xiàn)程是333333:%@",[NSThread currentThread]);
    // 網(wǎng)絡(luò)請(qǐng)求三
    [[AFHTTPSessionManager manager] POST:@"www.baidu.com" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        dispatch_group_leave(group);
        NSLog(@"success 此次返回的是333333 線(xiàn)程是:%@",[NSThread currentThread]);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        dispatch_group_leave(group);
        NSLog(@"failure 此次返回的是333333 線(xiàn)程是:%@",[NSThread currentThread]);
    }];
});
// 所有網(wǎng)絡(luò)請(qǐng)求結(jié)束后會(huì)來(lái)到這個(gè)方法
dispatch_group_notify(group, queue, ^{
    NSLog(@"所有網(wǎng)絡(luò)請(qǐng)求完畢1 線(xiàn)程是:%@",[NSThread currentThread]);
    dispatch_async(dispatch_get_main_queue(), ^{
        // 刷新UI
        NSLog(@"主線(xiàn)程刷新UI  線(xiàn)程是:%@",[NSThread currentThread]);
    });
});

在隊(duì)列組的使用中,創(chuàng)建的隊(duì)列不同,也會(huì)稍微有些區(qū)別:

  • 創(chuàng)建串行隊(duì)列 -- 網(wǎng)絡(luò)請(qǐng)求的開(kāi)始無(wú)序,且在同一線(xiàn)程
  • 創(chuàng)建全局并發(fā)隊(duì)列 -- 網(wǎng)絡(luò)請(qǐng)求的開(kāi)始無(wú)序,且線(xiàn)程不固定
  • 入組和出組必須和任務(wù)數(shù)相對(duì)應(yīng) - dispatch_group_enter(group)dispatch_group_leave(group)如數(shù)量不對(duì)應(yīng)會(huì)崩潰

此處有圖:

隊(duì)列組- 有序隊(duì)列.png
隊(duì)列組 - 全局并發(fā)隊(duì)列.png
最后編輯于
?著作權(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)容

  • 原創(chuàng)內(nèi)容,轉(zhuǎn)載請(qǐng)注明出處: http://m.itdecent.cn/p/ac11fe7ef78c 前言 多線(xiàn)...
    抱緊我的小鯉魚(yú)閱讀 8,904評(píng)論 6 78
  • GCD (Grand Central Dispatch) :iOS4 開(kāi)始引入,使用更加方便,程序員只需要將任務(wù)添...
    池鵬程閱讀 1,443評(píng)論 0 2
  • 2017.9.15(205—9/99)《焦點(diǎn)解決65》 感恩——堅(jiān)持21天能量誦讀已經(jīng)完成六篇。在每天堅(jiān)持誦...
    方正省閱讀 353評(píng)論 0 3
  • 你喜歡什么,我便討厭什么,因?yàn)槲矣憛捘?。我看?jiàn)與你有關(guān)的一切東西,我就分外心悸。
    Courageux閱讀 189評(píng)論 0 0
  • 好久沒(méi)有發(fā)感慨了,已經(jīng)過(guò)了無(wú)病呻吟的年齡,也看多了為了博取眼球故意激化某個(gè)觀點(diǎn)的內(nèi)容,總覺(jué)得這個(gè)世界安寧不安寧真跟...
    祭酒青詞閱讀 461評(píng)論 0 0

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