1、Dispatch Group
需要在大量任務(wù)都執(zhí)行完成后,執(zhí)行其他任務(wù),可以用 Dispatch Group
// 可以理解為一個(gè)任務(wù)組,組內(nèi)的任務(wù)完成后就會(huì)調(diào)用dispatch_group_notify
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_group_async(group, queue, ^{
for (int i = 0; i < 1000; i++) {
if (i == 999) {
NSLog(@"11111111");
}
}
});
dispatch_group_async(group, queue, ^{
NSLog(@"22222222");
});
dispatch_group_async(group, queue, ^{
NSLog(@"33333333");
});
dispatch_group_notify(group, queue, ^{
NSLog(@"done");
});
對于網(wǎng)絡(luò)請求這種異步任務(wù),還需要使用 dispatch_group_enter和dispatch_group_leave,來手動(dòng)處理下,先上代碼
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_group_enter(group);
dispatch_async(queue, ^{
NSLog(@"任務(wù)1開始");
sleep(2);
NSLog(@"任務(wù)1結(jié)束");
dispatch_group_leave(group);
});
dispatch_group_enter(group);
dispatch_async(queue, ^{
NSLog(@"任務(wù)2開始");
sleep(1);
NSLog(@"任務(wù)2結(jié)束");
dispatch_group_leave(group);
});
dispatch_group_notify(group, queue, ^{
NSLog(@"完成了");
});
輸出為
17:31:39.314251+0800 testP[29849:2247791] 任務(wù)2開始
17:31:39.314251+0800 testP[29849:2247785] 任務(wù)1開始
17:31:40.317949+0800 testP[29849:2247791] 任務(wù)2結(jié)束
17:31:41.318231+0800 testP[29849:2247785] 任務(wù)1結(jié)束
17:31:41.318588+0800 testP[29849:2247785] 完成了
可以看到任務(wù)1和任務(wù)2同時(shí)執(zhí)行,因?yàn)槿蝿?wù)1耗時(shí)2秒,所以在任務(wù)2后1秒完成,然后發(fā)出通知,
dispatch_group_enter和dispatch_group_leave總是成對出現(xiàn),不然可能導(dǎo)致group沒有被釋放,從而沒有notify;或者group提前釋放,導(dǎo)致EXC_BAD_INSTRUCTION,group提前釋放
dispatch_group_enter和dispatch_group_leave可以理解為給group添加手動(dòng)計(jì)數(shù),dispatch_group_enter會(huì)給group加1,dispatch_group_leave就是減一,group初始計(jì)數(shù)為0。
當(dāng)group初始計(jì)數(shù)為0時(shí),就會(huì)執(zhí)行notify通知,比如如下代碼
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_group_notify(group, queue, ^{
NSLog(@"完成了");
});
dispatch_group_enter(group);
dispatch_async(queue, ^{
NSLog(@"任務(wù)1開始");
sleep(2);
NSLog(@"任務(wù)1結(jié)束");
dispatch_group_leave(group);
});
dispatch_group_enter(group);
dispatch_async(queue, ^{
NSLog(@"任務(wù)2開始");
sleep(1);
NSLog(@"任務(wù)2結(jié)束");
dispatch_group_leave(group);
});
輸出為
17:45:46.296758+0800 testP[30209:2259157] 任務(wù)2開始
17:45:46.296758+0800 testP[30209:2259158] 任務(wù)1開始
17:45:46.296766+0800 testP[30209:2259150] 完成了
17:45:47.301499+0800 testP[30209:2259157] 任務(wù)2結(jié)束
17:45:48.299812+0800 testP[30209:2259158] 任務(wù)1結(jié)束
將dispatch_group_notify移到最前,就不會(huì)在group完成后得到notify,而是提前執(zhí)行了
2、dispatch_barrier_sync 和 dispatch_barrier_async

dispatch_async(queue, ^{
NSLog(@"1");
});
dispatch_async(queue, ^{
NSLog(@"2");
});
dispatch_async(queue, ^{
NSLog(@"3");
});
// dispatch_barrier_sync 這個(gè)和 dispatch_async與dispatch_sync之間的區(qū)別類似
dispatch_barrier_async(queue, ^{
NSLog(@"000000");
});
dispatch_async(queue, ^{
NSLog(@"4");
});
dispatch_async(queue, ^{
NSLog(@"5");
});
dispatch_async(queue, ^{
NSLog(@"6");
});
3、dispatch_semaphore
1、dispatch_semaphore_create 創(chuàng)建一個(gè)semaphore 就是創(chuàng)建一個(gè)全局的變量,小于0時(shí)會(huì)阻塞當(dāng)前線程
2、dispatch_semaphore_signal 發(fā)送一個(gè)信號(hào) 給信號(hào)量加1
3、dispatch_semaphore_wait 等待信號(hào) 給信號(hào)量減1
這個(gè)東西本質(zhì)是就是立flag,讓flag小于0,線程就阻塞了,只有讓flag大于0,才能繼續(xù)
網(wǎng)上的說明例子
// 創(chuàng)建隊(duì)列組
dispatch_group_t group = dispatch_group_create();
// 創(chuàng)建信號(hào)量,并且設(shè)置值為10
dispatch_semaphore_t semaphore = dispatch_semaphore_create(10);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i = 0; i < 100; i++){
/*
* 由于是異步執(zhí)行的,所以每次循環(huán)Block里面的dispatch_semaphore_signal根本還沒有執(zhí)行就會(huì)執(zhí)行dispatch_semaphore_wait,
* 從而semaphore-1.當(dāng)循環(huán)10此后,semaphore等于0,則會(huì)阻塞線程,直到執(zhí)行了Block的dispatch_semaphore_signal 才會(huì)繼續(xù)執(zhí)行
*/
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_group_async(group, queue, ^{
NSLog(@"%i",i);
sleep(2);
// 每次發(fā)送信號(hào)則semaphore會(huì)+1,
dispatch_semaphore_signal(semaphore);
});
}
應(yīng)用1 網(wǎng)絡(luò)請求
_block BOOL isok = NO;
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
Engine *engine = [[Engine alloc] init];
[engine queryCompletion:^(BOOL isOpen) {
isok = isOpen;
dispatch_semaphore_signal(sema);
} onError:^(int errorCode, NSString *errorMessage) {
isok = NO;
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
// todo what you want to do after net callback
應(yīng)用2 獲取權(quán)限
//創(chuàng)建通訊簿的引用
addBook=ABAddressBookCreateWithOptions(NULL, NULL);
//創(chuàng)建一個(gè)出事信號(hào)量為0的信號(hào)
dispatch_semaphore_t sema=dispatch_semaphore_create(0);
//申請?jiān)L問權(quán)限
ABAddressBookRequestAccessWithCompletion(addBook, ^(bool greanted, CFErrorRef error)
{
//greanted為YES是表示用戶允許,否則為不允許
if (!greanted) {
tip=1;
}
//發(fā)送一次信號(hào)
dispatch_semaphore_signal(sema);
});
//等待信號(hào)觸發(fā)
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);