GCD 常見面試點

在最近的 iOS 面試過程中,GCD 是屬于必問的問題州疾,接觸過不少 GCD 相關(guān)的面試題,有關(guān) GCD 的面試點大多數(shù)都是最大線程數(shù)量控制和任務(wù)分組皇拣,在這里做一個總結(jié)严蓖,方便大家進行參考。

GCD 控制線程數(shù)量

GCD 不像 NSOperation 那樣有直接提供線程數(shù)量控制方法,但是通過 GCD 的 semaphore 功能一樣可以達到控制線程數(shù)量的效果谈飒。

  1. dispatch_semaphore_create(long value); 利用給定的值創(chuàng)建一個新的可計數(shù)的信號量
  2. dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout); 如果信號量大于 0 岂座,信號量減 1 ,執(zhí)行程序杭措。否則等待信號量
  3. dispatch_semaphore_signal(dispatch_semaphore_t dsema); 增加信號量
// 控制線程數(shù)量
- (void)runMaxThreadCountWithGCD
{
    dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrentRunMaxThreadCountWithGCD", DISPATCH_QUEUE_CONCURRENT);
    dispatch_queue_t serialQueue = dispatch_queue_create("serialRunMaxThreadCountWithGCD", DISPATCH_QUEUE_SERIAL);
    // 創(chuàng)建一個semaphore,并設(shè)置最大信號量费什,最大信號量表示最大線程數(shù)量
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
    // 使用循環(huán)往串行隊列 serialQueue 增加 10 個任務(wù)
    for (int i = 0; i < 10 ; i++) {
        dispatch_async(serialQueue, ^{
            // 只有當(dāng)信號量大于 0 的時候,線程將信號量減 1手素,程序向下執(zhí)行
            // 否則線程會阻塞并且一直等待鸳址,直到信號量大于 0
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            dispatch_async(concurrentQueue, ^{
                NSLog(@"%@ 執(zhí)行任務(wù)一次  i = %d",[NSThread currentThread],i);
                // 當(dāng)線程任務(wù)執(zhí)行完成之后,發(fā)送一個信號泉懦,增加信號量稿黍。
                dispatch_semaphore_signal(semaphore);
            });
        });
    }
    NSLog(@"%@ 執(zhí)行任務(wù)結(jié)束",[NSThread currentThread]);
}

執(zhí)行結(jié)果如下,只有 number 3 和 number 4 這 2 個線程在執(zhí)行

<NSThread: 0x60c00007c600>{number = 1, name = main} 執(zhí)行任務(wù)結(jié)束
<NSThread: 0x60c00027a340>{number = 3, name = (null)} 執(zhí)行任務(wù)一次  i = 0
<NSThread: 0x608000263a00>{number = 4, name = (null)} 執(zhí)行任務(wù)一次  i = 1
<NSThread: 0x60c00027a340>{number = 3, name = (null)} 執(zhí)行任務(wù)一次  i = 3
<NSThread: 0x608000263a00>{number = 4, name = (null)} 執(zhí)行任務(wù)一次  i = 2
<NSThread: 0x60c00027a340>{number = 3, name = (null)} 執(zhí)行任務(wù)一次  i = 4
<NSThread: 0x608000263a00>{number = 4, name = (null)} 執(zhí)行任務(wù)一次  i = 5
<NSThread: 0x60c00027a340>{number = 3, name = (null)} 執(zhí)行任務(wù)一次  i = 6
<NSThread: 0x608000263a00>{number = 4, name = (null)} 執(zhí)行任務(wù)一次  i = 7
<NSThread: 0x60c00027a340>{number = 3, name = (null)} 執(zhí)行任務(wù)一次  i = 8
<NSThread: 0x608000263a00>{number = 4, name = (null)} 執(zhí)行任務(wù)一次  i = 9

GCD 任務(wù)分組

GCD 的 dispatch_group_t 功能可以將多個任務(wù)分組崩哩,等待分組里面的所有任務(wù)執(zhí)行完成之后巡球,GCD 的 dispatch_group_notify 方法可以通知。通常會配合一些常見的場景來考察邓嘹,比如同時上傳 10 張圖片酣栈,全部上傳完成后通知用戶。

// 任務(wù)分組
- (void)runGroupWithGCD
{
    dispatch_queue_t concurrentQueue = dispatch_queue_create("runGroupWithGCD", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t group =  dispatch_group_create();
    for (int i = 0; i < 10 ; i++) {
        dispatch_group_async(group, concurrentQueue, ^{
            NSLog(@"%@ 執(zhí)行任務(wù)一次",[NSThread currentThread]);
        });
    }

    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"%@ 執(zhí)行任務(wù)結(jié)束",[NSThread currentThread]);
    });
}

將所有的任務(wù)都加入 group 汹押,等待所有的任務(wù)執(zhí)行完成后矿筝,dispatch_group_notify 會被調(diào)用。

<NSThread: 0x608000265180>{number = 4, name = (null)} 執(zhí)行任務(wù)一次
<NSThread: 0x604000079a40>{number = 6, name = (null)} 執(zhí)行任務(wù)一次
<NSThread: 0x60c000268780>{number = 5, name = (null)} 執(zhí)行任務(wù)一次
<NSThread: 0x60c000267dc0>{number = 3, name = (null)} 執(zhí)行任務(wù)一次
<NSThread: 0x608000265080>{number = 9, name = (null)} 執(zhí)行任務(wù)一次
<NSThread: 0x600000265480>{number = 7, name = (null)} 執(zhí)行任務(wù)一次
<NSThread: 0x60c00007f9c0>{number = 8, name = (null)} 執(zhí)行任務(wù)一次
<NSThread: 0x608000264f40>{number = 10, name = (null)} 執(zhí)行任務(wù)一次
<NSThread: 0x604000079a40>{number = 6, name = (null)} 執(zhí)行任務(wù)一次
<NSThread: 0x608000265180>{number = 4, name = (null)} 執(zhí)行任務(wù)一次
<NSThread: 0x60000006d180>{number = 1, name = main} 執(zhí)行任務(wù)結(jié)束

GCD 任務(wù)分組和線程數(shù)量控制

利用 GCD 的 dispatch_group_t 和 semaphore 功能棚贾,我們可以做到控制線程數(shù)量窖维,并且在所有任務(wù)執(zhí)行完成之后得到通知。

// 任務(wù)分組 + 線程數(shù)量控制
- (void)runMaxCountInGroupWithGCD
{
    dispatch_queue_t concurrentQueue = dispatch_queue_create("runGroupWithGCD", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t group =  dispatch_group_create();
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);

    for (int i = 0; i < 10 ; i++) {
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        dispatch_group_async(group, concurrentQueue, ^{
            NSLog(@"%@ 執(zhí)行任務(wù)一次",[NSThread currentThread]);
            dispatch_semaphore_signal(semaphore);
        });
    }
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"%@ 執(zhí)行任務(wù)結(jié)束",[NSThread currentThread]);
    });
}

執(zhí)行之后妙痹,我們可以看到既控制了線程數(shù)量铸史,也在執(zhí)行任務(wù)完成之后得到了通知。

<NSThread: 0x604000269b40>{number = 3, name = (null)} 執(zhí)行任務(wù)一次
<NSThread: 0x608000264780>{number = 4, name = (null)} 執(zhí)行任務(wù)一次
<NSThread: 0x604000269b40>{number = 3, name = (null)} 執(zhí)行任務(wù)一次
<NSThread: 0x608000264780>{number = 4, name = (null)} 執(zhí)行任務(wù)一次
<NSThread: 0x608000264780>{number = 4, name = (null)} 執(zhí)行任務(wù)一次
<NSThread: 0x608000264780>{number = 4, name = (null)} 執(zhí)行任務(wù)一次
<NSThread: 0x604000269b40>{number = 3, name = (null)} 執(zhí)行任務(wù)一次
<NSThread: 0x608000264780>{number = 4, name = (null)} 執(zhí)行任務(wù)一次
<NSThread: 0x604000269b40>{number = 3, name = (null)} 執(zhí)行任務(wù)一次
<NSThread: 0x60400007aa40>{number = 1, name = main} 執(zhí)行任務(wù)結(jié)束
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末细诸,一起剝皮案震驚了整個濱河市沛贪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌震贵,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件水评,死亡現(xiàn)場離奇詭異猩系,居然都是意外死亡,警方通過查閱死者的電腦和手機中燥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門寇甸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事拿霉∫髦龋” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵绽淘,是天一觀的道長涵防。 經(jīng)常有香客問我,道長沪铭,這世上最難降的妖魔是什么壮池? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮杀怠,結(jié)果婚禮上椰憋,老公的妹妹穿的比我還像新娘。我一直安慰自己赔退,他們只是感情好橙依,可當(dāng)我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著硕旗,像睡著了一般票编。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上卵渴,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天慧域,我揣著相機與錄音,去河邊找鬼浪读。 笑死昔榴,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的碘橘。 我是一名探鬼主播互订,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼痘拆!你這毒婦竟也來了仰禽?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤纺蛆,失蹤者是張志新(化名)和其女友劉穎吐葵,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體桥氏,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡温峭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了字支。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凤藏。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡奸忽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出揖庄,到底是詐尸還是另有隱情栗菜,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布蹄梢,位于F島的核電站疙筹,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏检号。R本人自食惡果不足惜腌歉,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望齐苛。 院中可真熱鬧翘盖,春花似錦、人聲如沸凹蜂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽玛痊。三九已至汰瘫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間擂煞,已是汗流浹背混弥。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留对省,地道東北人蝗拿。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像蒿涎,于是被迫代替她去往敵國和親哀托。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,786評論 2 345

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