GCD的相關(guān)使用

一、同步執(zhí)行 + 主隊(duì)列

/**
 * 同步執(zhí)行 + 主隊(duì)列
 * 特點(diǎn)(主線(xiàn)程調(diào)用):互等卡主不執(zhí)行。
 * 特點(diǎn)(其他線(xiàn)程調(diào)用):不會(huì)開(kāi)啟新線(xiàn)程,執(zhí)行完一個(gè)任務(wù),再執(zhí)行下一個(gè)任務(wù)。
 */
- (void)syncMain {
    NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印當(dāng)前線(xiàn)程
    NSLog(@"開(kāi)啟");
    
    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_sync(queue, ^{
        NSLog(@"1---%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"2---%@",[NSThread currentThread]);
    });
    
    NSLog(@"結(jié)束");
}

運(yùn)行結(jié)果:

currentThread---<NSThread: 0x600001904240>{number = 1, name = main}
開(kāi)啟

線(xiàn)程死鎖。為什么呢?
- (void)syncMain {} ----> 任務(wù)AGCD同步任務(wù) ----> 任務(wù)B
??????任務(wù)A在主隊(duì)列,并且已經(jīng)開(kāi)始執(zhí)行(打印出currentThread),這個(gè)時(shí)候任務(wù)B被加入到主隊(duì)列中,并且同步執(zhí)行,且不能開(kāi)新的線(xiàn)程。
??????任務(wù)B得等Block函數(shù)執(zhí)行完成,才能返回,然而主隊(duì)列是串行的,得等任務(wù)A執(zhí)行完才能去執(zhí)行任務(wù)B的Block。
??????造成了任務(wù)A在等任務(wù)B完成才能繼續(xù)執(zhí)行,但是串行隊(duì)列中,又不能讓任務(wù)B在任務(wù)A未完成之前開(kāi)始執(zhí)行,相互等待,造成了死鎖。

二、同步執(zhí)行 + 并發(fā)隊(duì)列

/**
 * 同步執(zhí)行 + 并發(fā)隊(duì)列
 * 特點(diǎn):在當(dāng)前線(xiàn)程中執(zhí)行任務(wù),不會(huì)開(kāi)啟新線(xiàn)程,執(zhí)行完一個(gè)任務(wù),再執(zhí)行下一個(gè)任務(wù)。
 */
- (void)syncConcurrent {
    NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印當(dāng)前線(xiàn)程
    NSLog(@"開(kāi)啟");
    
    dispatch_queue_t queue = dispatch_queue_create("syncConcurrent", DISPATCH_QUEUE_CONCURRENT);
    dispatch_sync(queue, ^{
        NSLog(@"1---%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"2---%@",[NSThread currentThread]);
    });
    
    NSLog(@"結(jié)束");
}

運(yùn)行結(jié)果:

currentThread---<NSThread: 0x600003e0c1c0>{number = 1, name = main}
開(kāi)啟
1---<NSThread: 0x600003e0c1c0>{number = 1, name = main}
2---<NSThread: 0x600003e0c1c0>{number = 1, name = main}
結(jié)束

三、異步執(zhí)行 + 并發(fā)隊(duì)列

/**
 * 異步執(zhí)行 + 并發(fā)隊(duì)列
 * 特點(diǎn):可以開(kāi)啟多個(gè)線(xiàn)程,任務(wù)交替(同時(shí))執(zhí)行。
 */
- (void)asyncConcurrent {
    NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印當(dāng)前線(xiàn)程
    NSLog(@"開(kāi)啟");
    
    dispatch_queue_t queue = dispatch_queue_create("asyncConcurrent", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        NSLog(@"1---%@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"2---%@",[NSThread currentThread]);
    });
    
    NSLog(@"結(jié)束");
}

運(yùn)行結(jié)果:

currentThread---<NSThread: 0x600000d48980>{number = 1, name = main}
開(kāi)啟
結(jié)束
1---<NSThread: 0x600000d019c0>{number = 5, name = (null)}
2---<NSThread: 0x600000d00500>{number = 6, name = (null)}

四、同步執(zhí)行 + 串行隊(duì)列

/**
 * 同步執(zhí)行 + 串行隊(duì)列
 * 特點(diǎn):不會(huì)開(kāi)啟新線(xiàn)程,在當(dāng)前線(xiàn)程執(zhí)行任務(wù)。任務(wù)是串行的,執(zhí)行完一個(gè)任務(wù),再執(zhí)行下一個(gè)任務(wù)。
 */
- (void)syncSerial {
    NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印當(dāng)前線(xiàn)程
    NSLog(@"開(kāi)啟");
    
    dispatch_queue_t queue = dispatch_queue_create("syncSerial", DISPATCH_QUEUE_SERIAL);
    dispatch_sync(queue, ^{
        NSLog(@"1---%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"2---%@",[NSThread currentThread]);
    });
    
    NSLog(@"結(jié)束");
}

運(yùn)行結(jié)果:

currentThread---<NSThread: 0x600001284240>{number = 1, name = main}
開(kāi)啟
1---<NSThread: 0x600001284240>{number = 1, name = main}
2---<NSThread: 0x600001284240>{number = 1, name = main}
結(jié)束

五、異步執(zhí)行 + 串行隊(duì)列

/**
 * 異步執(zhí)行 + 串行隊(duì)列
 * 特點(diǎn):會(huì)開(kāi)啟新線(xiàn)程,但是因?yàn)槿蝿?wù)是串行的,執(zhí)行完一個(gè)任務(wù),再執(zhí)行下一個(gè)任務(wù)。
 */
- (void)asyncSerial {
    NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印當(dāng)前線(xiàn)程
    NSLog(@"開(kāi)啟");
    
    dispatch_queue_t queue = dispatch_queue_create("asyncConcurrent", DISPATCH_QUEUE_SERIAL);
    dispatch_async(queue, ^{
        NSLog(@"1---%@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"2---%@",[NSThread currentThread]);
    });
    
    NSLog(@"結(jié)束");
}

運(yùn)行結(jié)果:

currentThread---<NSThread: 0x6000025ac580>{number = 1, name = main}
開(kāi)啟
結(jié)束
1---<NSThread: 0x6000025fc680>{number = 4, name = (null)}
2---<NSThread: 0x6000025fc680>{number = 4, name = (null)}

六、其他函數(shù)用法

1、dispatch_after

- (void)GCDDelay {
    NSLog(@"current_%@",[NSThread currentThread]);
    //主隊(duì)列延時(shí)
    dispatch_time_t when_main = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
    dispatch_after(when_main, dispatch_get_main_queue(), ^{
        NSLog(@"main_%@",[NSThread currentThread]);
    });
    
    //全局隊(duì)列延時(shí)
    dispatch_time_t when_global = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
    dispatch_after(when_global, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"global_%@",[NSThread currentThread]);
    });
    
    //自定義隊(duì)列延時(shí)
    dispatch_queue_t customeQue = dispatch_queue_create("customeQue", DISPATCH_QUEUE_SERIAL);
    dispatch_time_t when_global_custom = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
    dispatch_after(when_global_custom, customeQue, ^{
        NSLog(@"when_global_custom_%@",[NSThread currentThread]);
    });
}
current_<NSThread: 0x600003fe8980>{number = 1, name = main}
main_<NSThread: 0x600003fe8980>{number = 1, name = main}
when_global_custom_<NSThread: 0x600003fa58c0>{number = 7, name = (null)}
global_<NSThread: 0x600003fad280>{number = 5, name = (null)}

??????我們可以看到,當(dāng)隊(duì)列是主隊(duì)列時(shí),任務(wù)是在主線(xiàn)程執(zhí)行;當(dāng)隊(duì)列為全局或自定義時(shí),任務(wù)是在子線(xiàn)程中執(zhí)行

2、dispatch_once

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

    NSLog(@"current_%@",[NSThread currentThread]);
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSLog(@"%@",[NSThread currentThread]);
    });
}
current_<NSThread: 0x600001cf8900>{number = 1, name = main}
<NSThread: 0x600001cf8900>{number = 1, name = main}

??????程序運(yùn)行期間,只會(huì)執(zhí)行一次打印,任務(wù)在主線(xiàn)程中執(zhí)行

3、dispatch_group_async & dispatch_group_notify

- (void)GCDGroup {
    
    NSLog(@"start_%@",[NSThread currentThread]);
    
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"1---%@",[NSThread currentThread]);
    });
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"2---%@",[NSThread currentThread]);
    });
    dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"3---%@",[NSThread currentThread]);
    });
    NSLog(@"end_%@",[NSThread currentThread]);
}
start_<NSThread: 0x6000032a0980>{number = 1, name = main}
end_<NSThread: 0x6000032a0980>{number = 1, name = main}
1---<NSThread: 0x6000032a8880>{number = 6, name = (null)}
2---<NSThread: 0x6000032ed4c0>{number = 3, name = (null)}
3---<NSThread: 0x6000032ed4c0>{number = 3, name = (null)}

dispatch_group_asyncdispatch_get_global_queue時(shí)會(huì)開(kāi)辟新的線(xiàn)程執(zhí)行任務(wù),任務(wù)會(huì)在子線(xiàn)程中執(zhí)行
dispatch_group_notify只會(huì)在dispatch_group_async都執(zhí)行完后才會(huì)執(zhí)行

4、dispatch_barrier_async

- (void)GCDBarrier {
    
    NSLog(@"start_%@",[NSThread currentThread]);
    dispatch_queue_t myQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
    
    dispatch_async(myQueue, ^{
        NSLog(@"1---%@",[NSThread currentThread]);
    });
    dispatch_async(myQueue, ^{
        NSLog(@"2---%@",[NSThread currentThread]);
    });
    //同步sync
    dispatch_barrier_sync(myQueue, ^{
        NSLog(@"barrier---%@",[NSThread currentThread]);
    });
    dispatch_async(myQueue, ^{
        NSLog(@"3---%@",[NSThread currentThread]);
    });
    dispatch_async(myQueue, ^{
        NSLog(@"4---%@",[NSThread currentThread]);
    });
    
    NSLog(@"end_%@",[NSThread currentThread]);
}
myQueue為自定義時(shí):
start_<NSThread: 0x600001044980>{number = 1, name = main}
2---<NSThread: 0x600001008a80>{number = 6, name = (null)}
1---<NSThread: 0x60000104db80>{number = 5, name = (null)}
barrier---<NSThread: 0x600001044980>{number = 1, name = main}
end_<NSThread: 0x600001044980>{number = 1, name = main}
3---<NSThread: 0x60000104db80>{number = 5, name = (null)}
4---<NSThread: 0x600001008a80>{number = 6, name = (null)}

myQueue為:dispatch_get_global_queue(0,0)時(shí)
start_<NSThread: 0x600001f90a00>{number = 1, name = main}
barrier---<NSThread: 0x600001f90a00>{number = 1, name = main}
1---<NSThread: 0x600001fdacc0>{number = 6, name = (null)}
2---<NSThread: 0x600001fd5340>{number = 7, name = (null)}
3---<NSThread: 0x600001fdacc0>{number = 6, name = (null)}
end_<NSThread: 0x600001f90a00>{number = 1, name = main}
4---<NSThread: 0x600001fc5080>{number = 4, name = (null)}
  • 當(dāng)隊(duì)列為自定義時(shí),使用dispatch_barrier_sync ()后,任務(wù)3、4必須等任務(wù)1、2執(zhí)行完后才能執(zhí)行
  • 當(dāng)隊(duì)列是dispatch_get_global_queue(0,0)時(shí),就算使用了dispatch_barrier_sync (),執(zhí)行順序隨機(jī)不固定
  • 當(dāng)隊(duì)列是dispatch_get_main_queue()時(shí),死鎖

5、dispatch_apply

- (void)GCDApply {
    dispatch_queue_t myQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
    //重復(fù)執(zhí)行
    dispatch_apply(5, myQueue, ^(size_t i) {
        NSLog(@"第%@次_%@",@(i),[NSThread currentThread]);
    });
}
myQueue為串行:
start_<NSThread: 0x600003d70980>{number = 1, name = main}
第0次_<NSThread: 0x600003d70980>{number = 1, name = main}
第1次_<NSThread: 0x600003d70980>{number = 1, name = main}
第2次_<NSThread: 0x600003d70980>{number = 1, name = main}
第3次_<NSThread: 0x600003d70980>{number = 1, name = main}
第4次_<NSThread: 0x600003d70980>{number = 1, name = main}
end_<NSThread: 0x600003d70980>{number = 1, name = main}

myQueue為并行:
start_<NSThread: 0x6000009d0a00>{number = 1, name = main}
第3次_<NSThread: 0x600000995900>{number = 6, name = (null)}
第2次_<NSThread: 0x6000009d7540>{number = 4, name = (null)}
第0次_<NSThread: 0x6000009d0a00>{number = 1, name = main}
第1次_<NSThread: 0x600000984300>{number = 7, name = (null)}
第4次_<NSThread: 0x6000009852c0>{number = 5, name = (null)}
end_<NSThread: 0x6000009d0a00>{number = 1, name = main}
  • 用于重復(fù)執(zhí)行某個(gè)任務(wù)
  • 任務(wù)隊(duì)列是串行隊(duì)列時(shí),重復(fù)執(zhí)行的任務(wù)會(huì)按順序執(zhí)行
  • 任務(wù)隊(duì)列是并行隊(duì)列時(shí),重復(fù)執(zhí)行的任務(wù)會(huì)并發(fā)執(zhí)行

6、dispatch_semaphore_create & dispatch_semaphore_wait & dispatch_semaphore_signal

- (void)GCDSemaphor {
    NSLog(@"start_%@",[NSThread currentThread]);
    
    dispatch_queue_t myQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
    //創(chuàng)建信號(hào)量,初始值不能小于0
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
    
    //重復(fù)執(zhí)行
    dispatch_apply(5, myQueue, ^(size_t i) {
        //等待降低信號(hào)量,也就是信號(hào)量-1
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        NSLog(@"第%@次_%@",@(i),[NSThread currentThread]);
        //提高信號(hào)量,也就是信號(hào)量+1
        dispatch_semaphore_signal(semaphore);
    });
    NSLog(@"end_%@",[NSThread currentThread]);
}
start_<NSThread: 0x600003bf0bc0>{number = 1, name = main}
第0次_<NSThread: 0x600003bf0bc0>{number = 1, name = main}
第1次_<NSThread: 0x600003bf0bc0>{number = 1, name = main}
第2次_<NSThread: 0x600003bf0bc0>{number = 1, name = main}
第3次_<NSThread: 0x600003bf0bc0>{number = 1, name = main}
第4次_<NSThread: 0x600003bf0bc0>{number = 1, name = main}
end_<NSThread: 0x600003bf0bc0>{number = 1, name = main}

異步任務(wù)使用

- (void)GCDSemaphorAsync {
    NSLog(@"start_%@",[NSThread currentThread]);
    
    dispatch_queue_t myQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
    //創(chuàng)建信號(hào)量
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    
    dispatch_async(myQueue, ^{
        NSLog(@"第一次任務(wù)開(kāi)始_%@",[NSThread currentThread]);
        [NSThread sleepForTimeInterval:2];
        NSLog(@"第一次任務(wù)結(jié)束_%@",[NSThread currentThread]);
        //會(huì)將信號(hào)量的值加一
        dispatch_semaphore_signal(semaphore);
    });
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    
    dispatch_async(myQueue, ^{
        NSLog(@"第二次任務(wù)開(kāi)始_%@",[NSThread currentThread]);
        [NSThread sleepForTimeInterval:2];
        NSLog(@"第二次任務(wù)結(jié)束_%@",[NSThread currentThread]);
        //會(huì)將信號(hào)量的值加一
        dispatch_semaphore_signal(semaphore);
    });
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    
    dispatch_async(myQueue, ^{
        NSLog(@"第三次任務(wù)開(kāi)始_%@",[NSThread currentThread]);
        [NSThread sleepForTimeInterval:2];
        NSLog(@"第三次任務(wù)結(jié)束_%@",[NSThread currentThread]);
        //會(huì)將信號(hào)量的值加一
        dispatch_semaphore_signal(semaphore);
    });
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    
    NSLog(@"end_%@",[NSThread currentThread]);
}
start_<NSThread: 0x600002eb0a00>{number = 1, name = main}
第一次任務(wù)開(kāi)始_<NSThread: 0x600002eb9f40>{number = 6, name = (null)}
第一次任務(wù)結(jié)束_<NSThread: 0x600002eb9f40>{number = 6, name = (null)}
第二次任務(wù)開(kāi)始_<NSThread: 0x600002eb9f40>{number = 6, name = (null)}
第二次任務(wù)結(jié)束_<NSThread: 0x600002eb9f40>{number = 6, name = (null)}
第三次任務(wù)開(kāi)始_<NSThread: 0x600002eb9f40>{number = 6, name = (null)}
第三次任務(wù)結(jié)束_<NSThread: 0x600002eb9f40>{number = 6, name = (null)}
end_<NSThread: 0x600002eb0a00>{number = 1, name = main}
  • dispatch_semaphore_create創(chuàng)建信號(hào)量,初始值不能小于0
  • dispatch_semaphore_wait等待降低信號(hào)量,也就是信號(hào)量-1
  • dispatch_semaphore_signal提高信號(hào)量,也就是信號(hào)量+1
  • dispatch_semaphore_waitdispatch_semaphore_signal通常配對(duì)使用
主要作用:
  • 保持線(xiàn)程同步,將異步執(zhí)行任務(wù)轉(zhuǎn)換為同步執(zhí)行任務(wù)
  • 保證線(xiàn)程 安全,為線(xiàn)程加鎖
最后編輯于
?著作權(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)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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