iOS多線程中的實(shí)際方案之三GCD

GCD(基于C語(yǔ)言的底層API,用Block定義任務(wù))


GCD的核心概念


  • 將任務(wù)添加到隊(duì)列,并且指定執(zhí)行任務(wù)的函數(shù)
  • 任務(wù)使用 block 封裝
  • 任務(wù)的 block 沒(méi)有參數(shù)也沒(méi)有返回值
  • 執(zhí)行任務(wù)的函數(shù)
  • 異步 dispatch_async
    • 不用等待當(dāng)前語(yǔ)句執(zhí)行完畢,就可以執(zhí)行下一條語(yǔ)句
    • 會(huì)開(kāi)啟線程執(zhí)行 block 的任務(wù)
    • 異步是多線程的代名詞
  • 同步 dispatch_sync
    • 必須等待當(dāng)前語(yǔ)句執(zhí)行完畢,才會(huì)執(zhí)行下一條語(yǔ)句
    • 不會(huì)開(kāi)啟線程
    • 在當(dāng)前執(zhí)行 block 的任務(wù)
  • 隊(duì)列 - 負(fù)責(zé)調(diào)度任務(wù)
  • 串行隊(duì)列
    • 一次只能"調(diào)度"一個(gè)任務(wù)
    • dispatch_queue_create("serial", NULL);
  • 并發(fā)隊(duì)列
    • 一次可以"調(diào)度"多個(gè)任務(wù)
    • dispatch_queue_create("concurrent", DISPATCH_QUEUE_CONCURRENT);
  • 主隊(duì)列
    • 專(zhuān)門(mén)用來(lái)在主線程上調(diào)度任務(wù)的隊(duì)列
    • 不會(huì)開(kāi)啟線程
    • 在主線程空閑時(shí)才會(huì)調(diào)度隊(duì)列中的任務(wù)在主線程執(zhí)行
    • dispatch_get_main_queue();

GCD 演練


1.同步串行隊(duì)列

  • 任務(wù)會(huì)在當(dāng)前的線程中執(zhí)行,會(huì)阻塞當(dāng)前的線程
  • 開(kāi)發(fā)中很少使用
#pragma mark 同步串行隊(duì)列
void gcddemo1(){
// 1.創(chuàng)建一個(gè)串行隊(duì)列,意味著說(shuō)隊(duì)列里的任務(wù)是一個(gè)接著一個(gè)執(zhí)行(類(lèi)似于排隊(duì)跑步)dispatch_queue_t q = dispatch_queue_create("serial", DISPATCH_QUEUE_SERIAL);
// 2.往 ‘隊(duì)列中’ 添加 ‘任務(wù)’,這個(gè)任務(wù)是同步的,//同步意味著任務(wù)的執(zhí)行是在當(dāng)前線程中,如果當(dāng)前是主線程,任務(wù)就在主線程中運(yùn)行
for (int i = 0; i < 10; i++) {dispatch_sync(q, ^{
NSLog(@"%@ 任務(wù)%d",[NSThread currentThread],i);});
}}

2.異步串行隊(duì)列

  • 任務(wù)不在當(dāng)前的線程中執(zhí)行,會(huì)在子線程中執(zhí)行
  • 因?yàn)槭谴嘘?duì)列,所以會(huì)依次執(zhí)行任務(wù)
#pragma mark 異步串行隊(duì)列
void gcddemo2(){
// 1.創(chuàng)建一個(gè)串行隊(duì)列,意味著說(shuō)隊(duì)列里的任務(wù)是一個(gè)接著一個(gè)執(zhí)行(類(lèi)似于排隊(duì)跑步)dispatch_queue_t q = dispatch_queue_create("gz.itcast.cn", DISPATCH_QUEUE_SERIAL);
// 2.往 ‘隊(duì)列中’ 添加 ‘任務(wù)’,這個(gè)任務(wù)是異步的,// 異步意味著任務(wù)的執(zhí)行會(huì)開(kāi)啟新線程來(lái)執(zhí)行,我們稱(chēng)為子線程
for (int i = 0; i < 10; i++) {dispatch_async(q, ^{
NSLog(@"%@ 任務(wù)%d",[NSThread currentThread],i);});
}}

3.同步并發(fā)隊(duì)列

  • 任務(wù)會(huì)在當(dāng)前的線程中執(zhí)行,開(kāi)發(fā)中很少使用
  • 因?yàn)槭峭綀?zhí)行,所以隊(duì)列中的任務(wù)會(huì)依次執(zhí)行
#pragma mark 同步并行隊(duì)列
void gcddemo3(){
// 1.創(chuàng)建一個(gè)并行隊(duì)列,意味著說(shuō)隊(duì)列里的任務(wù)是搶著執(zhí)行(類(lèi)似于并排跑步比賽)dispatch_queue_t q = dispatch_queue_create("gz.itcast.cn", DISPATCH_QUEUE_CONCURRENT);
// 2.往 ‘隊(duì)列中’ 添加 ‘任務(wù)’,這個(gè)任務(wù)是同步的,同步意味著代碼的執(zhí)行是在當(dāng)前線程// 但是在同步任務(wù)中,并行隊(duì)列里的任務(wù)會(huì)依序執(zhí)行for (int i = 0; i < 10; i++) {
dispatch_sync(q, ^{NSLog(@"%@ 任務(wù)%d",[NSThread currentThread],i);
});}
}

4.異步并發(fā)隊(duì)列

  • 任務(wù)不在當(dāng)前的線程中執(zhí)行,會(huì)在子線程中執(zhí)行
  • 任務(wù)會(huì)搶占式地去執(zhí)
#pragma mark 異步并行隊(duì)列
void gcddemo4(){
// 1.創(chuàng)建一個(gè)并行隊(duì)列,意味著說(shuō)隊(duì)列里的任務(wù)是搶著執(zhí)行(類(lèi)似于并排跑步比賽)dispatch_queue_t q = dispatch_queue_create("gz.itcast.cn", DISPATCH_QUEUE_CONCURRENT);
// 2.往 ‘隊(duì)列中’ 添加 ‘任務(wù)’,這個(gè)任務(wù)是異步的,異步意味著任務(wù)的執(zhí)行是在子線程// 在異步任務(wù)中,并行隊(duì)列里的任務(wù)會(huì)搶占式執(zhí)行// 線程的開(kāi)銷(xiāo)由系統(tǒng)調(diào)試,任務(wù)的執(zhí)行順序是不同的for (int i = 0; i < 10; i++) {
dispatch_async(q, ^{
NSLog(@"%@ 任務(wù)%d",[NSThread currentThread],i);});
}}

5.全局隊(duì)列(和并發(fā)隊(duì)列的執(zhí)行效果相同)

  • 蘋(píng)果為了方便多線程序的設(shè)置,提供一個(gè)全局隊(duì)列,供所有的APP共同使用(日常開(kāi)發(fā)中,建議使用全局隊(duì)列)
  • 和并發(fā)隊(duì)列的區(qū)別:
    • 直接get使用
    • 并發(fā)隊(duì)列可以設(shè)置名字,但是全局對(duì)不可以
#pragma mark 全局隊(duì)列
void gcddemo5(){
// 1.獲取全局隊(duì)列,全局隊(duì)列供所有APP使用dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 2.往 ‘全局隊(duì)列’ 添加 ‘任務(wù)’// 2.1異步里添加同步dispatch_async(q, ^{
NSLog(@"異步任務(wù) %@ ",[NSThread currentThread]);for (int i = 0; i < 10; i++) {
//在同步任務(wù)中,全局隊(duì)列里的任務(wù)會(huì)順序執(zhí)行dispatch_sync(q, ^{
NSLog(@"%@ 任務(wù)%d",[NSThread currentThread],i);});
}});
//2.2同步里添加異步dispatch_sync(q, ^{
NSLog(@"同步任務(wù) %@ ",[NSThread currentThread]);for (int i = 0; i < 10; i++) {
//在異步任務(wù)中,全局隊(duì)列里的任務(wù)會(huì)搶?xiě)?zhàn)執(zhí)行dispatch_async(q, ^{
NSLog(@"%@ 任務(wù)%d",[NSThread currentThread],i);});
}});
}

6.主隊(duì)列

  • 主線程中不能使用同步,那樣會(huì)造成線程阻塞

7.Barrier 異步

  • 使用 dispatch_barrier_async 添加的 block 會(huì)在之前添加的 block 全部運(yùn)行結(jié)束之后,才在同一個(gè)線程順序執(zhí)行,從而保證對(duì)非線程安全的對(duì)象進(jìn)行正確的操作
  • dispatch_barrier 必須使用自定義的并發(fā)隊(duì)列
  • 舉例說(shuō)明:下載圖片,并將下載好的圖片添加到數(shù)組(可變的)里面,可變數(shù)組是線程不安全的,有可能出現(xiàn)多個(gè)線程同時(shí)向數(shù)組里面添加下載好的圖片,這樣有可能出現(xiàn)程序崩潰的情況

8.延遲執(zhí)行

  • 調(diào)用NSObject的方法
[self performSelector:@selector(run) withObject:nil afterDelay:2.0];
  • 使用GCD函數(shù)
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
(int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(),^{
          // 2秒后異步執(zhí)行這里的代碼...
});

9.調(diào)度組

  • 假如有3個(gè)異步操作要先執(zhí)行完,然后再到主線程中去做操作,此時(shí)使用調(diào)度組的效率是最高的。
// 1. 調(diào)度組
    dispatch_group_t group = dispatch_group_create();
    
    // 2. 隊(duì)列
    dispatch_queue_t q = dispatch_get_global_queue(0, 0);
    
    // 3. 將任務(wù)添加到隊(duì)列和調(diào)度組
    dispatch_group_async(group, q, ^{
        [NSThread sleepForTimeInterval:1.0];
        NSLog(@"任務(wù) 1 %@", [NSThread currentThread]);
    });
    dispatch_group_async(group, q, ^{
        NSLog(@"任務(wù) 2 %@", [NSThread currentThread]);
    });
    dispatch_group_async(group, q, ^{
        NSLog(@"任務(wù) 3 %@", [NSThread currentThread]);
    });
    
    // 4. 監(jiān)聽(tīng)所有任務(wù)完成
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"OVER %@", [NSThread currentThread]);
    });
    
    // 5. 判斷異步
    NSLog(@"come here");

自我小結(jié)


  • 異不異步?jīng)Q定是否是多線程
  • 異步不能確定任務(wù)的執(zhí)行順序
  • 串聯(lián):任務(wù)一個(gè)一個(gè)地執(zhí)行
  • 并發(fā):多個(gè)任務(wù)會(huì)一起執(zhí)行
  • 阻塞:使用嵌套:(串行 同步+同步) 會(huì)造成線程阻塞,因?yàn)榈谝粋€(gè)同步操作里面的任務(wù)會(huì)等第二同步操作里面的任務(wù)執(zhí)行完在執(zhí)行,而第二個(gè)同步操作里面的任務(wù)又會(huì)等第一個(gè)同步操作里面的任務(wù)完成,這就產(chǎn)生了循環(huán),兩個(gè)操作都不會(huì)執(zhí)行完成。
最后編輯于
?著作權(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)容

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