https://blog.csdn.net/Lu_Ca/article/details/80691965
1、dispatch_barrier_async
dispatch_barrier_async用于等待前面的任務(wù)執(zhí)行完畢后自己才執(zhí)行,而它后面的任務(wù)需等待它完成之后才執(zhí)行。一個典型的例子就是數(shù)據(jù)的讀寫,通常為了防止文件讀寫導(dǎo)致沖突,我們會創(chuàng)建一個串行的隊列,所有的文件操作都是通過這個隊列來執(zhí)行,比如FMDB,這樣就可以避免讀寫沖突。不過其實這樣效率是有提升的空間的,當(dāng)沒有更新數(shù)據(jù)時,讀操作其實是可以并行進行的,而寫操作需要串行的執(zhí)行,如何實現(xiàn)呢:
dispatch_queue_t queue = dispatch_queue_create("Database_Queue", DISPATCH_QUEUE_CONCURRENT);
? ? dispatch_async(queue, ^{
? ? ? ? NSLog(@"reading data1");
? ? });
? ? dispatch_async(queue, ^{
? ? ? ? NSLog(@"reading data2");
? ? });
? ? dispatch_barrier_async(queue, ^{
? ? ? ? NSLog(@"writing data1");
? ? ? ? [NSThread sleepForTimeInterval:1];
? ? });
? ? dispatch_async(queue, ^{
? ? ? ? [NSThread sleepForTimeInterval:1];
? ? ? ? NSLog(@"reading data3");
? ? });
執(zhí)行結(jié)果如下:
GCDTests[13360:584316] reading data2
GCDTests[13360:584317] reading data1
GCDTests[13360:584317] writing data1
GCDTests[13360:584317] reading data3
我們將寫數(shù)據(jù)的操作放在dispatch_barrier_async中,這樣能確保在寫數(shù)據(jù)的時候會等待前面的讀操作完成,而后續(xù)的讀操作也會等到寫操作完成后才能繼續(xù)執(zhí)行,提高文件讀寫的執(zhí)行效率。
2、dispatch_apply
dispatch_apply類似一個for循環(huán),會在指定的dispatch queue中運行block任務(wù)n次,如果隊列是并發(fā)隊列,則會并發(fā)執(zhí)行block任務(wù),dispatch_apply是一個同步調(diào)用,block任務(wù)執(zhí)行n次后才返回。
簡單的使用方法:
dispatch_queue_t queue = dispatch_queue_create("myqueue", DISPATCH_QUEUE_CONCURRENT);
//并發(fā)的運行一個block任務(wù)5次
dispatch_apply(5, queue, ^(size_t i) {
? ? NSLog(@"do a job %zu times",i+1);
});
NSLog(@"go on");
輸出結(jié)果:
GCDTests[10029:760640] do a job 2 times
GCDTests[10029:760640] do a job 1 times
GCDTests[10029:760640] do a job 3 times
GCDTests[10029:760640] do a job 5 times
GCDTests[10029:760640] do a job 4 times
GCDTests[10029:760640] go on
3、dispatch_block_notify
dispatch_block_notify當(dāng)觀察的某個block執(zhí)行結(jié)束之后立刻通知提交另一特定的block到指定的queue中執(zhí)行,該函數(shù)有三個參數(shù),第一參數(shù)是需要觀察的block,第二個參數(shù)是被通知block提交執(zhí)行的queue,第三參數(shù)是當(dāng)需要被通知執(zhí)行的block,函數(shù)的原型:
void dispatch_block_notify(dispatch_block_t block, dispatch_queue_t queue,
? ? ? ? dispatch_block_t notification_block);
具體使用的方法:
? ? dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
? ? dispatch_block_t previousBlock = dispatch_block_create(0, ^{
? ? ? ? NSLog(@"previousBlock begin");
? ? ? ? [NSThread sleepForTimeInterval:1];
? ? ? ? NSLog(@"previousBlock done");
? ? });
? ? dispatch_async(queue, previousBlock);
? ? dispatch_block_t notifyBlock = dispatch_block_create(0, ^{
? ? ? ? NSLog(@"notifyBlock");
? ? });
? ? //當(dāng)previousBlock執(zhí)行完畢后,提交notifyBlock到global queue中執(zhí)行
? ? dispatch_block_notify(previousBlock, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), notifyBlock);
運行結(jié)果:
GCDTests[17129:895673] previousBlock begin
GCDTests[17129:895673] previousBlock done
GCDTests[17129:895673] notifyBlock
4、dispatch_group_wait
dispatch_group_wait會同步地等待group中所有的block執(zhí)行完畢后才繼續(xù)執(zhí)行,類似于dispatch barrier
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
//將任務(wù)異步地添加到group中去執(zhí)行
dispatch_group_async(group,queue,^{ NSLog(@"block1"); });
dispatch_group_async(group,queue,^{ NSLog(@"block2"); });
dispatch_group_wait(group,DISPATCH_TIME_FOREVER);
NSLog(@"go on");
執(zhí)行結(jié)果如下,只有block1跟block2執(zhí)行完畢后才會執(zhí)行dispatch_group_wait后面的內(nèi)容。
GCDTests[954:41031] block2
GCDTests[954:41032] block1
GCDTests[954:40847] go on
5、dispatch_group_notify
功能與dispatch_group_wait類似,不過該過程是異步的,不會阻塞該線程,dispatch_group_notify有三個參數(shù)
void dispatch_group_notify(dispatch_group_t group, //要觀察的group
? ? ? ? ? ? ? ? ? ? ? ? ? dispatch_queue_t queue,? //block執(zhí)行的隊列
? ? ? ? ? ? ? ? ? ? ? ? ? dispatch_block_t block);? //當(dāng)group中所有任務(wù)執(zhí)行完畢之后要執(zhí)行的block
簡單的示意用法:
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group,queue,^{ NSLog(@"block1"); });
dispatch_group_async(group,queue,^{ NSLog(@"block2"); });
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
? ? NSLog(@"done");
});
NSLog(@"go on");
可以看到如下的執(zhí)行結(jié)果
GCDTests[1046:45104] go on
GCDTests[1046:45153] block1
GCDTests[1046:45152] block2
GCDTests[1046:45104] done