一. dispatch_group_t 用法
1. dispatch_group_t 執(zhí)行同步操作
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t globeQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_async(group, globeQ, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"1--over");
});
dispatch_group_async(group, globeQ, ^{
[NSThread sleepForTimeInterval:5];
NSLog(@"2--over");
});
dispatch_group_async(group, globeQ, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"3--over");
});
dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{
NSLog(@"全部結(jié)束......");
});
NSLog(@" waiting... ");
運(yùn)行,打印結(jié)果如下
2017-07-26 15:10:07.166248 測(cè)試用test[15173:289444] waiting...
2017-07-26 15:10:09.170468 測(cè)試用test[15173:289523] 3--over
2017-07-26 15:10:10.167656 測(cè)試用test[15173:289495] 1--over
2017-07-26 15:10:12.170615 測(cè)試用test[15173:289497] 2--over
2017-07-26 15:10:12.170749 測(cè)試用test[15173:289497] 全部結(jié)束......
從上面的步驟可以得出
I.異步操作,異步 并且 無序執(zhí)行;
II.三個(gè)dispatch_group 執(zhí)行全部完成之后,會(huì)執(zhí)行 dispatch_group_notify里面的block
III.waiting...立即執(zhí)行,dispatch_group_t不會(huì)阻塞當(dāng)前線程;
但是,當(dāng)dispatch_group_async的block里面執(zhí)行的是異步任務(wù),如果還是使用上面的方法你會(huì)發(fā)現(xiàn)異步任務(wù)還沒跑完就已經(jīng)進(jìn)入到了dispatch_group_notify里面的block.例如下面:
dispatch_group_t group = dispatch_group_create();
// dispatch_queue_t globeQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t concurrentQ = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_async(group, concurrentQ, ^{
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"1--over");
});
});
dispatch_group_async(group, concurrentQ, ^{
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[NSThread sleepForTimeInterval:5];
NSLog(@"2--over");
});
});
dispatch_group_async(group, concurrentQ, ^{
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"3--over");
});
});
dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{
NSLog(@"全部結(jié)束......");
});
NSLog(@" waiting... ");
運(yùn)行,打印結(jié)果如下
2017-07-26 15:23:14.959950 測(cè)試用test[15550:300115] waiting...
2017-07-26 15:23:14.960001 測(cè)試用test[15550:300152] 全部結(jié)束......
2017-07-26 15:23:16.962408 測(cè)試用test[15550:300168] 3--over
2017-07-26 15:23:17.960724 測(cè)試用test[15550:300154] 1--over
2017-07-26 15:23:19.962464 測(cè)試用test[15550:300164] 2--over
從上面的結(jié)果可看出, 當(dāng)執(zhí)行是異步操作的 使用上面的方法無法滿足要求.這時(shí)用到dispatch_group_enter和dispatch_group_leave就可以解決這個(gè)問題:
2. dispatch_group_t 執(zhí)行的是異步操作
示例
dispatch_group_t group = dispatch_group_create();
// dispatch_queue_t globeQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t concurrentQ = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_enter(group);
dispatch_async(concurrentQ, ^{
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"1--over");
dispatch_group_leave(group);
});
});
dispatch_group_enter(group);
dispatch_async(concurrentQ, ^{
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[NSThread sleepForTimeInterval:5];
NSLog(@"2--over");
dispatch_group_leave(group);
});
});
dispatch_group_enter(group);//可以寫在每個(gè)組前面,也可以全部提到任務(wù)最前面
dispatch_async(concurrentQ, ^{
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"3--over");
dispatch_group_leave(group);
});
});
dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{
NSLog(@"全部結(jié)束......");
});
NSLog(@" waiting... ");
創(chuàng)建好任務(wù)組后,執(zhí)行加入任務(wù)組的操作代碼。dispatch_enter和dispatch_leave要成對(duì)出現(xiàn),否則奔潰。
運(yùn)行,打印如下:
2017-07-26 15:35:09.359028 測(cè)試用test[15895:310263] waiting...
2017-07-26 15:35:11.362995 測(cè)試用test[15895:310296] 3--over
2017-07-26 15:35:12.361839 測(cè)試用test[15895:310297] 1--over
2017-07-26 15:35:14.364044 測(cè)試用test[15895:310321] 2--over
2017-07-26 15:35:14.364166 測(cè)試用test[15895:310321] 全部結(jié)束......
滿足需求,OK!!
二. dispatch_semaphore_t 用法
示例:
執(zhí)行的是同步操作
for (int i = 0; i<3; ++i) {
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_queue_t globeQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(globeQ, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"%d--over",i+1);
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"%d--through",i+1);
}
NSLog(@" waiting... ");
執(zhí)行的是異步操作
for (int i = 0; i<3; ++i) {
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
// dispatch_queue_t globeQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t concurrentQ = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQ, ^{
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"%d--over",i+1);
dispatch_semaphore_signal(semaphore);
});
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"%d--through",i+1);
}
NSLog(@" waiting... ");
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); 如果semaphore計(jì)數(shù)大于等于1.計(jì)數(shù)-1,返回,程序繼續(xù)運(yùn)行。如果計(jì)數(shù)為0,則等待。這里設(shè)置的等待時(shí)間是一直等待。dispatch_semaphore_signal(semaphore);計(jì)數(shù)+1.在這兩句代碼中間的執(zhí)行代碼,每次只會(huì)允許一個(gè)線程進(jìn)入,這樣就有效的保證了在多線程環(huán)境下,只能有一個(gè)線程進(jìn)入。
運(yùn)行,打印結(jié)果全部如下
2017-07-26 13:57:20.748453 測(cè)試用test[9697:223538] 1--over
2017-07-26 13:57:20.748523 測(cè)試用test[9697:223493] 1--through
2017-07-26 13:57:23.750806 測(cè)試用test[9697:223538] 2--over
2017-07-26 13:57:23.750881 測(cè)試用test[9697:223493] 2--through
2017-07-26 13:57:26.754020 測(cè)試用test[9697:223538] 3--over
2017-07-26 13:57:26.754095 測(cè)試用test[9697:223493] 3--through
2017-07-26 13:57:26.754117 測(cè)試用test[9697:223493] waiting...
從上面的步驟可以得出
I.異步操作,同步 并且 順序執(zhí)行;
II.waiting... 最后執(zhí)行,dispatch_semaphore_t 信號(hào)量會(huì)阻塞當(dāng)前進(jìn)程;
綜合對(duì)比,兩種方式都可以滿足 實(shí)現(xiàn)異步同步執(zhí)行的需求,具體選擇 就要看個(gè)人了...