GCD Group、Barrier裸影、Semaphore挣轨、NSOperationQueue使用

先貼上打印函數(shù):

- (void)p_printThread:(int)index {
    NSLog(@"%@-------%d", [NSThread currentThread], index);
}

1. Group

Group作用:在并發(fā)異步隊列中,等待執(zhí)行一系列任務后轩猩,再執(zhí)行一個任務卷扮。實現(xiàn)方式有兩種:notify和wait。
notify示例代碼:

dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, concurrentQueue, ^{ 
        [self p_printThread:1];
    });
    dispatch_group_async(group, concurrentQueue, ^{ 
        [self p_printThread:2];
    });
    dispatch_group_async(group, concurrentQueue, ^{
        [self p_printThread:3];
    });
    dispatch_group_async(group, concurrentQueue, ^{ 
        [self p_printThread:4];
    });
    // 使用dispatch_group_wait均践,可以阻塞線程晤锹,等待group的任務執(zhí)行完畢,才能繼續(xù)執(zhí)行后續(xù)任務
    // 使用dispatch_group_notify彤委,不會阻塞線程(group外的線程執(zhí)行順序不受影響)鞭铆,而且可以在執(zhí)行完成group的任務后進行操作
    dispatch_group_notify(group, concurrentQueue, ^{
        [self p_printThread:0];
    });

打印結(jié)果:

<NSThread: 0x610000260d80>{number = 4, name = (null)}-------2
<NSThread: 0x608000261400>{number = 5, name = (null)}-------3
<NSThread: 0x618000264f40>{number = 3, name = (null)}-------1
<NSThread: 0x610000260e40>{number = 6, name = (null)}-------4
<NSThread: 0x610000260e40>{number = 6, name = (null)}-------0

wait示例代碼:

dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();
    for (int i=0; i<4; i++)  {
        dispatch_group_enter(group);
        dispatch_async(concurrentQueue, ^{
            [self p_printThread:i+1];
        });   
        dispatch_group_leave(group);
    }
    // 使用dispatch_group_wait,可以阻塞線程焦影,等待group的任務執(zhí)行完畢
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    dispatch_async(dispatch_get_main_queue(), ^{
        // 主線程處理
        [self p_printThread:0];
    });

打印結(jié)果:

<NSThread: 0x600000076600>{number = 4, name = (null)}-------2
<NSThread: 0x600000076740>{number = 6, name = (null)}-------4
<NSThread: 0x610000073280>{number = 3, name = (null)}-------1
<NSThread: 0x608000076380>{number = 5, name = (null)}-------3
<NSThread: 0x60000007b240>{number = 1, name = main}-------0

結(jié)論:運行多次车遂,任務1封断、2、3舶担、4的順序不定澄港,但任務0總是最后一個。應用場景:單界面多請求完成后柄沮,主線程刷新界面;notify和wait的區(qū)別:wait會阻塞線程回梧,notify不會阻塞線程,較好一點

2. Barrier

Barrier作用:Barrier在并發(fā)異步隊列中起到承上啟下的作用(Barrier就像名字一樣祖搓,類似一個柵欄把前后的任務隔開了)狱意。Barrier前后任務執(zhí)行順序為:Barrier前面的線程(多個的話,仍是并行)--->barrier線程--->barrier后面的線程(多個的話拯欧,仍是并行)详囤。需要注意的是:Barrier在全局并發(fā)隊列不起作用,只有在自己創(chuàng)建的并發(fā)隊列才起作用镐作。

示例代碼:

// barrier在dispatch_get_global_queue創(chuàng)建的并行隊列中不起作用藏姐,需要使用dispatch_queue_create來創(chuàng)建的并行隊列才可以
    //dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(concurrentQueue, ^(){
        [self p_printThread:1];
    });
    dispatch_async(concurrentQueue, ^(){
        [self p_printThread:2];
    });
    dispatch_async(concurrentQueue, ^(){
        [self p_printThread:3];
    });
    dispatch_barrier_async(concurrentQueue, ^(){
        [self p_printThread:0];
    });
    dispatch_async(concurrentQueue, ^(){
        [self p_printThread:4];
    });
    dispatch_async(concurrentQueue, ^(){
        [self p_printThread:5];
    });
    dispatch_async(concurrentQueue, ^(){
        [self p_printThread:6];
    });

打印結(jié)果:

<NSThread: 0x600000079300>{number = 4, name = (null)}-------2
<NSThread: 0x6000000790c0>{number = 5, name = (null)}-------3
<NSThread: 0x610000076100>{number = 3, name = (null)}-------1
<NSThread: 0x610000076100>{number = 3, name = (null)}-------0
<NSThread: 0x610000076100>{number = 3, name = (null)}-------4
<NSThread: 0x600000079300>{number = 4, name = (null)}-------6
<NSThread: 0x600000078d40>{number = 6, name = (null)}-------5

結(jié)論:運行多次后可以看出,Barrier的任務0總是在任務1该贾、2羔杨、3之后,而且總是在任務4杨蛋、5兜材、6之前,但是任務1逞力、2曙寡、3的執(zhí)行順序不定,任務4寇荧、5举庶、6的執(zhí)行順序也不定。Barrier的任務就像“柵欄”一樣隔開了前后的任務揩抡。

3. Semaphore

Semaphore作用:信號量可以用來控制同時訪問資源的線程數(shù)量:比如系統(tǒng)只有兩個資源可以用户侥,有三個線程要訪問,那么只能允許兩個線程同時訪問捅膘,第三個線程應當?shù)却Y源被釋放后再訪問添祸。使用信號量可以實現(xiàn)類似于NSOperationQueue里的并發(fā)控制:信號數(shù)>0,執(zhí)行任務寻仗;信號數(shù)<=0刃泌,阻塞線程
示例代碼:

// 下面的例子只允許3個線程同時執(zhí)行
dispatch_semaphore_t semaphore = dispatch_semaphore_create(3);// 創(chuàng)建一個信號量,初始值為3
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    for (int i=0; i<10; i++) {
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);// 計數(shù)-1
        dispatch_async(concurrentQueue, ^{
            [self p_printThread:i];
            sleep(5);
            dispatch_semaphore_signal(semaphore);// 計數(shù)+1
        });
    }

打印結(jié)果:
<NSThread: 0x608000077b80>{number = 5, name = (null)}-------2
<NSThread: 0x610000074fc0>{number = 3, name = (null)}-------0
<NSThread: 0x6000000787c0>{number = 4, name = (null)}-------1

<NSThread: 0x6000000787c0>{number = 4, name = (null)}-------3
<NSThread: 0x610000074fc0>{number = 3, name = (null)}-------4
<NSThread: 0x608000077b80>{number = 5, name = (null)}-------5

<NSThread: 0x6000000787c0>{number = 4, name = (null)}-------7
<NSThread: 0x608000077b80>{number = 5, name = (null)}-------6
<NSThread: 0x610000074fc0>{number = 3, name = (null)}-------8

<NSThread: 0x610000074fc0>{number = 3, name = (null)}-------9
結(jié)論:由于信號量的值為3,每次只能同時執(zhí)行3個線程里的任務

4. NSOperationQueue

NSOperationQueue作用:
1.將NSOperation添加到NSOperationQueue耙替,使其異步執(zhí)行 === GCD并行異步隊列亚侠。2.NSOperationQueue可以設置依賴關系 ~= GCD Group notify / GCD Group Wait / GCD Barrier。
3.可以設置最大并發(fā)數(shù)量(同時執(zhí)行的線程數(shù)) === GCD 信號量
示例代碼:

NSOperationQueue *operationQueue = [NSOperationQueue new];
    NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{
        [self p_printThread:1];
        sleep(5);
    }];
    NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{
        [self p_printThread:2];
        sleep(5);
    }];
    NSBlockOperation *blockOperation3 = [NSBlockOperation blockOperationWithBlock:^{
        [self p_printThread:3];
        sleep(5);
    }];
    NSBlockOperation *blockOperation4 = [NSBlockOperation blockOperationWithBlock:^{
        [self p_printThread:4];
        sleep(5);
    }];
    
    // 2.NSOperationQueue可以設置依賴關系 ~=  GCD Group notify / GCD Group Wait / GCD Barrier
    [blockOperation1 addDependency:blockOperation2];
  
    // 3.可以設置最大并發(fā)數(shù)量(同時執(zhí)行的線程數(shù)) === GCD 信號量
    operationQueue.maxConcurrentOperationCount = 1;

    [operationQueue addOperations:@[blockOperation1, blockOperation2, blockOperation3, blockOperation4] waitUntilFinished:YES];

打印結(jié)果:

<NSThread: 0x600000078300>{number = 3, name = (null)}-------2

<NSThread: 0x600000078300>{number = 3, name = (null)}-------1

<NSThread: 0x60000007aa80>{number = 4, name = (null)}-------3

<NSThread: 0x60000007aa80>{number = 4, name = (null)}-------4

結(jié)論:運行多次可以看出俗扇,每次只能執(zhí)行一個線程里的任務(這個類似信號量的控制)硝烂;雖然任務1、2铜幽、3滞谢、4的順序不定,但是任務1總是在任務2的后面(類似group的notify和wait)除抛。對比可以看出NSOperationQueue使用更方便一些狮杨,語法也更接近Objective-C。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末到忽,一起剝皮案震驚了整個濱河市橄教,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌喘漏,老刑警劉巖护蝶,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異翩迈,居然都是意外死亡持灰,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進店門帽馋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來搅方,“玉大人,你說我怎么就攤上這事绽族。” “怎么了衩藤?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵吧慢,是天一觀的道長。 經(jīng)常有香客問我赏表,道長检诗,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任瓢剿,我火速辦了婚禮逢慌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘间狂。我一直安慰自己攻泼,他們只是感情好,可當我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著忙菠,像睡著了一般何鸡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上牛欢,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天骡男,我揣著相機與錄音,去河邊找鬼傍睹。 笑死隔盛,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的拾稳。 我是一名探鬼主播骚亿,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼熊赖!你這毒婦竟也來了来屠?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤震鹉,失蹤者是張志新(化名)和其女友劉穎俱笛,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體传趾,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡迎膜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了浆兰。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片磕仅。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖簸呈,靈堂內(nèi)的尸體忽然破棺而出榕订,到底是詐尸還是另有隱情,我是刑警寧澤蜕便,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布劫恒,位于F島的核電站,受9級特大地震影響轿腺,放射性物質(zhì)發(fā)生泄漏两嘴。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一族壳、第九天 我趴在偏房一處隱蔽的房頂上張望憔辫。 院中可真熱鬧,春花似錦仿荆、人聲如沸贰您。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽枉圃。三九已至功茴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間孽亲,已是汗流浹背坎穿。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留返劲,地道東北人玲昧。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像篮绿,于是被迫代替她去往敵國和親孵延。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,678評論 2 354

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