iOS GCD group 多請求異步 semaphore 多請求同步

在做項目的時候往往會出現(xiàn)多圖上傳的功能,而恰巧服務器可能只支持單張上傳痪署,所以你要遍歷請求尸红,而全部上傳完成后可能還要刷新列表啊或者給個提示框啊等需求。
有些人可能會一個網(wǎng)絡請求成功回調(diào)里面再嵌套一個,類推逛薇,如果上傳9張圖就要嵌套9次捺疼,很顯然這樣的代碼看上去有點low而且非并發(fā)耗時比較慢,推薦使用gcd group 組永罚。話不多說上代碼:

//創(chuàng)建一個組
dispatch_group_t group = dispatch_group_create();
for (int i = 0; i <9; I++)
{//模仿多個網(wǎng)絡請求
    dispatch_group_async(group,dispatch_get_global_queue(0, 0), ^{
        //異步網(wǎng)絡請求
        
        int x = arc4random() % 5;
        //模擬網(wǎng)絡請求快慢不確定的情況
        sleep(x);
        
        NSLog(@"group 請求成功OR請求失敗 %d!",i);
    });
}
NSLog(@"group開始 網(wǎng)絡請求!");

dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    //網(wǎng)絡請求完畢 回到主線程更新UI 或者做些其它的操作
    NSLog(@"group所有請求完畢!!!");
});

使用dispatch_group_async函數(shù)將多個任務關聯(lián)到一個Dispatch Group和相應的queue中啤呼,group會并發(fā)地同時執(zhí)行這些任務。而且Dispatch Group可以用來阻塞一個線程, 直到group關聯(lián)的所有的任務完成執(zhí)行調(diào)用dispatch_group_notify方法,這樣就達到了想要的效果。

ABF94C9D-3542-4C6C-A30C-2BA6DCDDB02B.png

當然你也可以不使用dispatch_group_async函數(shù),轉(zhuǎn)而使用dispatch_group_enter和dispatch_group_leave,注意這里要配套使用哦延塑。
dispatch_group_enter:通知group,下面的任務馬上要放到group中執(zhí)行了醇锚。
dispatch_group_leave:通知group,任務完成了坯临,該任務要從group中移除了。

//創(chuàng)建一個組
dispatch_group_t group = dispatch_group_create();
for (int i = 0; i <9; I++)
{//模仿多個網(wǎng)絡請求
    
    dispatch_group_enter(group);
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        //異步網(wǎng)絡請求
        
        int x = arc4random() % 5;
        //模擬網(wǎng)絡請求快慢不確定的情況
        sleep(x);
        NSLog(@"group 請求成功OR請求失敗 %d!",i);
        
        dispatch_group_leave(group);
    });
}
NSLog(@"group開始 網(wǎng)絡請求!");

dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    //網(wǎng)絡請求完畢 回到主線程更新UI 或者做些其它的操作
    NSLog(@"group所有請求完畢!!!");
});
A27BFDF3-170D-40D9-BD7F-3802FAF82D56.png

還有一種情況恋昼,比如要做一個相冊功能看靠,也是多圖上傳,但是要有規(guī)律按順序上傳液肌。這里就推薦使用dispatch_semaphore_t 信號量,也是利用線程阻塞來實現(xiàn)挟炬。直接上代碼:

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    /// 創(chuàng)建一個線程"001" 確保之后不要阻塞主線程
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        /// 創(chuàng)建一個信號量 數(shù)值為1  信號量可以讓線程阻塞等待
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    
        for (int i = 0; i<9; i++) {
            /// 模仿9個請求任務
            /// 執(zhí)行dispatch_semaphore_wait 信號量數(shù)值 -1.
            /// 當i為0此時的信號量數(shù)值為0, 當此時的信號量大于等于0繼續(xù)執(zhí)行wait函數(shù)下面的語句.
            /// 當i為1此時的信號量數(shù)值為-1, 阻塞當前線程 阻塞時長為DISPATCH_TIME_FOREVER, 不執(zhí)行wait函數(shù)下面的語句.
            /// 只有等到執(zhí)行i為0 的 dispatch_semaphore_signal 方法執(zhí)行, 信號量數(shù)值+1 為0, 喚醒 繼續(xù)執(zhí)行wait函數(shù)下面的語句.
            /// 以此類推循環(huán).
            NSLog(@"當前線程:%@",[NSThread currentThread]);
        
            /// ******這是一個網(wǎng)絡請求開始******
            dispatch_async(dispatch_get_global_queue(0, 0), ^{
                /// 模擬異步網(wǎng)絡請求
                int x = arc4random() % 2;
                /// 模擬網(wǎng)絡請求快慢
                sleep(x);
                NSLog(@"執(zhí)行任務代號:%d",i);
                /// 任務結(jié)束 信號量數(shù)值+1 解放線程"001" 阻塞
                dispatch_semaphore_signal(semaphore);
            });
            /// ******這是一個網(wǎng)絡請求結(jié)束******

            /// 信號量減1 變?yōu)樨摂?shù) 當前線程"001" 阻塞
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        }
    });
}
image.png

如果需要兩者結(jié)合使用呢也是可以的,這樣即能按順序上傳嗦哆,又能在上傳后收到通知做一些提示或者其它操作谤祖,請看代碼:

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    /// 創(chuàng)建一個線程"001" 確保之后不要阻塞主線程
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
    
        dispatch_group_t group = dispatch_group_create();
    
        /// 創(chuàng)建一個信號量 數(shù)值為0
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
        for (int i = 0; i<9; i++)
        {
            /// 模仿9個請求任務
            dispatch_group_async(group,dispatch_get_global_queue(0, 0), ^{
//                /// 異步網(wǎng)絡請求
//                int x = arc4random() % 2;
//                /// 模擬網(wǎng)絡請求快慢不確定的情況
//                sleep(x);

                NSLog(@"執(zhí)行任務:%d 線程:%@",i,[NSThread currentThread]);
                /// 任務結(jié)束 信號量數(shù)值+1 解放線程"001" 阻塞
                dispatch_semaphore_signal(semaphore);
            });
        
            /// 信號量減1 變?yōu)樨摂?shù) 當前線程"001" 阻塞
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            //NSLog(@"阻塞線程:%@",[NSThread currentThread]);
        }
    
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{
            /// 網(wǎng)絡請求完畢 回到主線程更新UI 或者做些其它的操作
            NSLog(@"所有任務執(zhí)行完畢!!!");
        });
    });
}
image.png

想要順序(同步)執(zhí)行異步任務的話,可以把一個個異步任務放在串行隊列里面去執(zhí)行老速,代碼如下:

dispatch_queue_t queue = dispatch_queue_create("serial",DISPATCH_QUEUE_SERIAL);
///在串行隊列中 執(zhí)行第一個異步任務
dispatch_async(queue, ^{
    NSLog(@"1---%@", [NSThread currentThread]);
    [NSThread sleepForTimeInterval:5];
    NSLog(@"xxxxxxxxxxxxxx");
});
///在串行隊列中 執(zhí)行第二個異步任務
dispatch_async(queue, ^{
    NSLog(@"2---%@", [NSThread currentThread]);
});
///在串行隊列中 執(zhí)行第三個異步任務
dispatch_async(queue, ^{
    NSLog(@"3---%@", [NSThread currentThread]);
});
E3F126184247B6AF82003F339439F266.jpg

如果有不同見解歡迎討論粥喜,有錯誤還請指出,博主加以改正橘券,謝謝!
轉(zhuǎn)載請說明出處额湘,代碼在這里。請不要吝嗇您的star

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末旁舰,一起剝皮案震驚了整個濱河市锋华,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌箭窜,老刑警劉巖毯焕,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異磺樱,居然都是意外死亡纳猫,警方通過查閱死者的電腦和手機婆咸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來续担,“玉大人擅耽,你說我怎么就攤上這事∥镉觯” “怎么了乖仇?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長询兴。 經(jīng)常有香客問我乃沙,道長,這世上最難降的妖魔是什么诗舰? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任警儒,我火速辦了婚禮,結(jié)果婚禮上眶根,老公的妹妹穿的比我還像新娘蜀铲。我一直安慰自己,他們只是感情好属百,可當我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布记劝。 她就那樣靜靜地躺著,像睡著了一般族扰。 火紅的嫁衣襯著肌膚如雪厌丑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天渔呵,我揣著相機與錄音怒竿,去河邊找鬼。 笑死扩氢,一個胖子當著我的面吹牛耕驰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播类茂,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼耍属,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了巩检?” 一聲冷哼從身側(cè)響起厚骗,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎兢哭,沒想到半個月后领舰,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年冲秽,在試婚紗的時候發(fā)現(xiàn)自己被綠了舍咖。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡锉桑,死狀恐怖排霉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情民轴,我是刑警寧澤攻柠,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站后裸,受9級特大地震影響瑰钮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜微驶,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一浪谴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧因苹,春花似錦苟耻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蘸秘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蝗茁,已是汗流浹背醋虏。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留哮翘,地道東北人颈嚼。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像饭寺,于是被迫代替她去往敵國和親阻课。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容

  • iOS 多線程系列 -- 基礎概述iOS 多線程系列 -- pthreadiOS 多線程系列 -- NSThrea...
    shannoon閱讀 849評論 0 2
  • 目錄:iOS多線程(一)--pthread艰匙、NSThreadiOS多線程(二)--GCD詳解iOS多線程(三)--...
    Claire_wu閱讀 1,076評論 0 6
  • 一限煞、簡單介紹下將會用到的一些東西 英語不好就不翻譯官方文檔了.. 1、dispatch_group_async S...
    Albert新榮閱讀 1,727評論 0 1
  • GCD筆記 總結(jié)一下多線程部分,最強大的無疑是GCD,那么先從這一塊部分講起. Dispatch Queue的種類...
    jins_1990閱讀 761評論 0 1
  • GCD (Grand Central Dispatch) :iOS4 開始引入员凝,使用更加方便署驻,程序員只需要將任務添...
    池鵬程閱讀 1,337評論 0 2