GCD-基本概念以及隊列和同步異步組合后的情況

1.多線程中的的一些基本概念

進程:對于操作系統(tǒng)來說,一個可以運行的應(yīng)用程序(app)就是一個進程换衬。
線程:一個app中可能會同時處理不同的任務(wù)痰驱,比如請求數(shù)據(jù)和頁面刷新,請求數(shù)據(jù)會在子線程處理瞳浦,頁面刷新會在主線程處理担映,一個程序中可以有多個線程。
隊列:在GCD中的隊列就是指用來存放任務(wù)的等待隊列叫潦,把任務(wù)添加到隊列后蝇完,我們不需要跟線程打交道。GCD在后段管理著一個線程池矗蕊。
隊列可以分為串行隊列和并發(fā)隊列短蜕。
串行隊列:在這個隊列中的任務(wù)會按照FIFO一個一個執(zhí)行,只會開啟一個線程傻咖。
并發(fā)隊列:這個隊列中的任務(wù)會按照FIFO出來朋魔,但是會同時開辟多個線程執(zhí)行。
主隊列:是一個全局可用的串行隊列卿操。
全局隊列:一個全局可用的并發(fā)隊列警检。

同步執(zhí)行(dispatch_sync):同步執(zhí)行就是指使用 dispatch_sync方法將任務(wù)同步的添加到隊列里,在添加的任務(wù)執(zhí)行結(jié)束之前硬纤,當前線程會被阻塞解滓,然后會一直等待,直到任務(wù)完成筝家。
dispatch_sync添加的任務(wù)只能在當前線程執(zhí)行洼裤,不具備開啟新線程的能力

異步執(zhí)行(dispatch_async):異步執(zhí)行就是指使用dispatch_async方法將任務(wù)異步的添加到隊列里,它不需要等待任務(wù)執(zhí)行結(jié)束溪王,不需要做任何等待就能繼續(xù)執(zhí)行任務(wù)
dispatch_async添加的任務(wù)可以在新的線程中執(zhí)行任務(wù)腮鞍,具備開啟新線程的能力,但并不一定會開啟新線程

2.不同隊列對應(yīng)同步異步執(zhí)行的情況

2.1 同步執(zhí)行主隊列中的任務(wù)

2.1.1在主線程中同步執(zhí)行主隊列的任務(wù)

dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"在主線程同步添加主隊列任務(wù)");
    });

運行結(jié)果卡死莹菱,GCD-主線程上同步執(zhí)行主隊列任務(wù)卡死

2.1.2在子線程中同步執(zhí)行主隊列任務(wù)

NSLog(@"進入子線程之前,當前線程:%@", [NSThread currentThread]);
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"進入子線程,當前線程:%@", [NSThread currentThread]);
        for (int i = 0; i < 10; i++) {
            dispatch_sync(dispatch_get_main_queue(), ^{
                NSLog(@"在子線程中開啟的主隊列同步任務(wù)i=%d,當前線程:%@", i, [NSThread currentThread]);
            });
        }
        NSLog(@"子線程中的主隊列任務(wù)已經(jīng)完成,當前線程:%@", [NSThread currentThread]);
    });
    NSLog(@"子線程代碼已經(jīng)結(jié)束,當前線程:%@", [NSThread currentThread]);

運行結(jié)果:主隊列中的任務(wù)在主線程按順序執(zhí)行移国。主隊列中的任務(wù)等主線程執(zhí)行完再執(zhí)行。

2.2異步執(zhí)行主隊列的任務(wù)

2.2.1在主線程中異步執(zhí)行主隊列的任務(wù)

NSLog(@"主隊列任務(wù)添加前");
        for (int i = 0; i < 10; i++) {
            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"在子線程中開啟的主隊列異步任務(wù)i=%d,當前線程:%@", i, [NSThread currentThread]);
            });
        }
    NSLog(@"主隊列任務(wù)添加后");

運行結(jié)果:

主隊列任務(wù)添加前
主隊列任務(wù)添加后
在子線程中開啟的主隊列異步任務(wù)i=0,當前線程:<NSThread: 0x600000795480>{number = 1, name = main}
在子線程中開啟的主隊列異步任務(wù)i=1,當前線程:<NSThread: 0x600000795480>{number = 1, name = main}
······
在子線程中開啟的主隊列異步任務(wù)i=9,當前線程:<NSThread: 0x600000795480>{number = 1, name = main}

先執(zhí)行主隊列之外主線程中的代碼道伟,然后按順序在主線程執(zhí)行主隊列中的任務(wù)迹缀。

2.2.2在子線程中異步執(zhí)行主隊列的任務(wù)

NSLog(@"進入子線程之前,當前線程:%@", [NSThread currentThread]);
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"進入子線程,當前線程:%@", [NSThread currentThread]);
        for (int i = 0; i < 10; i++) {
            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"在子線程中開啟的主隊列異步任務(wù)i=%d,當前線程:%@", i, [NSThread currentThread]);
            });
        }
        NSLog(@"子線程中的主隊列任務(wù)已經(jīng)完成,當前線程:%@", [NSThread currentThread]);
    });
    NSLog(@"子線程代碼已經(jīng)結(jié)束,當前線程:%@", [NSThread currentThread]);

運行結(jié)果:先執(zhí)行主隊列之外主線程中的代碼使碾,然后按順序在主線程執(zhí)行主隊列中的任務(wù)。
2.3串行隊列同步執(zhí)行

dispatch_queue_t queue = dispatch_queue_create("testSerialSync", DISPATCH_QUEUE_SERIAL);
    NSLog(@"當前線程為%@", [NSThread currentThread]);
    for (int i = 0; i < 10; i++) {
        dispatch_sync(queue, ^{
            NSLog(@"i = %d,當前線程為%@", i, [NSThread currentThread]);
        });
    }
    for (int j = 0; j < 10; j++) {
        NSLog(@"j = %d, 當前線程為%@", j, [NSThread currentThread]);
    }

結(jié)果: 不開辟子線程祝懂,在主線程按順序執(zhí)行票摇。主線程中的代碼會等串行隊列中的任務(wù)結(jié)束后在執(zhí)行。
2.4串行隊列異步執(zhí)行

dispatch_queue_t queue = dispatch_queue_create("testSerialSync", DISPATCH_QUEUE_SERIAL);
    NSLog(@"當前線程為%@", [NSThread currentThread]);
    for (int i = 0; i < 10; i++) {
        dispatch_async(queue, ^{
            NSLog(@"i = %d,當前線程為%@", i, [NSThread currentThread]);
        });
    }
    for (int j = 0; j < 10; j++) {
        NSLog(@"j = %d, 當前線程為%@", j, [NSThread currentThread]);
    }

結(jié)果:開辟一個子線程砚蓬,同步隊列中的任務(wù)在子線程按順序執(zhí)行矢门。主線程的代碼會和串行隊列中的任務(wù)同時執(zhí)行。
2.5并發(fā)隊列同步執(zhí)行

dispatch_queue_t queue = dispatch_queue_create("testSerialSync", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"當前線程為%@", [NSThread currentThread]);
    for (int i = 0; i < 10; i++) {
        dispatch_sync(queue, ^{
            NSLog(@"i = %d,當前線程為%@", i, [NSThread currentThread]);
        });
    }
    for (int j = 0; j < 10; j++) {
        NSLog(@"j = %d, 當前線程為%@", j, [NSThread currentThread]);
    }
結(jié)果:不開辟子線程灰蛙,在主線程中按順序執(zhí)行祟剔,主線程中的任務(wù)等并發(fā)隊列中的任務(wù)執(zhí)行完再執(zhí)行。

2.6并發(fā)隊列異步執(zhí)行

dispatch_queue_t queue = dispatch_queue_create("testSerialSync", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"當前線程為%@", [NSThread currentThread]);
    for (int i = 0; i < 10; i++) {
        dispatch_async(queue, ^{
            NSLog(@"i = %d,當前線程為%@", i, [NSThread currentThread]);
        });
    }
    NSLog(@"當前線程為%@", [NSThread currentThread]);

結(jié)果:開辟多個線程摩梧,和主線程之后的代碼同時執(zhí)行物延,主線程按順序執(zhí)行。
總結(jié):
在主線程中同步執(zhí)行主隊列的任務(wù): 卡死

在子線程中同步執(zhí)行主隊列任務(wù): 主隊列中的任務(wù)在主線程按順序執(zhí)行障本。主隊列中的任務(wù)等主線程之后的代碼執(zhí)行完再執(zhí)行教届。

在主線程中異步執(zhí)行主隊列的任務(wù): 先執(zhí)行主隊列之外主線程中的代碼,然后按順序在主線程執(zhí)行主隊列中的任務(wù)驾霜。

在子線程中異步執(zhí)行主隊列的任務(wù): 先執(zhí)行主隊列之外主線程中的代碼,然后按順序在主線程執(zhí)行主隊列中的任務(wù)买置。

串行隊列同步執(zhí)行:不開辟子線程粪糙,在主線程按順序執(zhí)行。主線程中的代碼會等串行隊列中的任務(wù)結(jié)束后在執(zhí)行忿项。

串行隊列異步執(zhí)行:開辟一個子線程蓉冈,同步隊列中的任務(wù)在子線程按順序執(zhí)行。主線程的代碼會和串行隊列中的任務(wù)同時執(zhí)行轩触。

并發(fā)隊列同步執(zhí)行:不開辟子線程寞酿,在主線程中按順序執(zhí)行,主線程中的任務(wù)等并發(fā)隊列中的任務(wù)執(zhí)行完再執(zhí)行脱柱。

并發(fā)隊列異步執(zhí)行:開辟多個線程伐弹,和主線程之后的代碼同時執(zhí)行,主線程按順序執(zhí)行榨为。

3.隊列的掛起和恢復(fù)

掛起指定隊列:dispatch_suspend(queue);
恢復(fù)指定隊列:dispatchp_resume(queue);
示例:

dispatch_queue_t queue = dispatch_queue_create("queueSuspend", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        NSLog(@"隊列沒有掛起前添加的任務(wù)開始執(zhí)行");
        sleep(3);
        NSLog(@"隊列沒有掛起前添加的任務(wù)執(zhí)行結(jié)束");
    });
    NSLog(@"隊列還沒有掛起");
    dispatch_suspend(queue);
    NSLog(@"隊列已經(jīng)掛起");
    dispatch_async(queue, ^{
        NSLog(@"隊列被掛起之后添加的任務(wù)開始執(zhí)行");
    });
    NSLog(@"5秒后恢復(fù)隊列");
    sleep(5);
    dispatch_resume(queue);
    NSLog(@"隊列已經(jīng)恢復(fù)");

打印結(jié)果:

2020-02-28 15:52:12.132254+0800 Test[23449:1607212] 隊列還沒有掛起
2020-02-28 15:52:12.132259+0800 Test[23449:1607343] 隊列沒有掛起前添加的任務(wù)開始執(zhí)行
2020-02-28 15:52:12.132424+0800 Test[23449:1607212] 隊列已經(jīng)掛起
2020-02-28 15:52:12.132525+0800 Test[23449:1607212] 5秒后恢復(fù)隊列
2020-02-28 15:52:15.136284+0800 Test[23449:1607343] 隊列沒有掛起前添加的任務(wù)執(zhí)行結(jié)束
2020-02-28 15:52:17.132924+0800 Test[23449:1607212] 隊列已經(jīng)恢復(fù)
2020-02-28 15:52:17.132924+0800 Test[23449:1607343] 隊列被掛起之后添加的任務(wù)開始執(zhí)行

由結(jié)果可以知道惨好,dispatch_suspend函數(shù)可以掛起隊列,dispatch_resume函數(shù)可以恢復(fù)隊列随闺,
隊列掛起后不會馬上停止當前在執(zhí)行的任務(wù)日川,而是會執(zhí)行完當前的任務(wù),暫停后面隊列中的任務(wù)矩乐。

4.GCD的延時函數(shù)

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (3)( * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
代碼塊
});
這個代碼的意思是在當前時間的3秒后在主隊列執(zhí)行相應(yīng)的代碼塊龄句。

5.GCD取消任務(wù)執(zhí)行

5.1 iOS8之后可以調(diào)用dispatch_block_cancel來取消

5.2定義外部變量,用于標記block是否需要取消

GCD取消任務(wù)執(zhí)行

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市分歇,隨后出現(xiàn)的幾起案子透葛,更是在濱河造成了極大的恐慌,老刑警劉巖卿樱,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件僚害,死亡現(xiàn)場離奇詭異,居然都是意外死亡繁调,警方通過查閱死者的電腦和手機萨蚕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蹄胰,“玉大人岳遥,你說我怎么就攤上這事≡U” “怎么了浩蓉?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長宾袜。 經(jīng)常有香客問我捻艳,道長,這世上最難降的妖魔是什么庆猫? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任认轨,我火速辦了婚禮,結(jié)果婚禮上月培,老公的妹妹穿的比我還像新娘嘁字。我一直安慰自己,他們只是感情好杉畜,可當我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布纪蜒。 她就那樣靜靜地躺著,像睡著了一般此叠。 火紅的嫁衣襯著肌膚如雪纯续。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天拌蜘,我揣著相機與錄音杆烁,去河邊找鬼。 笑死简卧,一個胖子當著我的面吹牛兔魂,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播举娩,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼析校,長吁一口氣:“原來是場噩夢啊……” “哼构罗!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起智玻,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤遂唧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后吊奢,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盖彭,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年页滚,在試婚紗的時候發(fā)現(xiàn)自己被綠了召边。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡裹驰,死狀恐怖隧熙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情幻林,我是刑警寧澤贞盯,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站沪饺,受9級特大地震影響躏敢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜随闽,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一父丰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧掘宪,春花似錦、人聲如沸攘烛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽坟漱。三九已至鼠次,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間芋齿,已是汗流浹背腥寇。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留觅捆,地道東北人赦役。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像栅炒,于是被迫代替她去往敵國和親掂摔。 傳聞我的和親對象是個殘疾皇子术羔,可洞房花燭夜當晚...
    茶點故事閱讀 43,486評論 2 348