iOS常见的多线程开发方式有NSThread、NSOPeration和GCD,抽象程度依次提高,GCD是最抽象的,使用起来最简单,但相对来说功能有限,比如不能cancel任务,这也算是一点遗憾吧。
今天主要记录下学习dispatch_barrier_async中遇到的问题(其实是自己没仔细看Apple文档),dispatch_barrier_async是在执行完前面的任务后它才执行,而且它后面的任务等它执行完成之后才会执行(先后顺序是按照添加到queue的次序),但该API适用的场景是dispatch queue必须是用DISPATCH_QUEUE_CONCURRENT属性创建的queue,而不能是用系统定义好的dispatch_get_global_queue,下面是测试代码:
1、当dispatch queue是dispatch_get_global_queue时,dispatch_barrier_async失效:
1 - (void)viewDidLoad { 2 [super viewDidLoad]; 3 // Do any additional setup after loading the view, typically from a nib. 4 NSLog(@"main thread:%p",[NSThread currentThread]); 5 [self testBarrierBlockWithGlobalQueue]; 6 } 7 - (void)testBarrierBlockWithGlobalQueue 8 { 9 NSLog(@"current iOS Version:%.1f",[[[UIDevice currentDevice] systemVersion] floatValue]); 10 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 11 dispatch_async(queue, ^{ 12 [NSThread sleepForTimeInterval:2]; 13 NSLog(@"Excute block 1:%p",[NSThread currentThread]); 14 }); 15 dispatch_async(queue, ^{ 16 [NSThread sleepForTimeInterval:3]; 17 NSLog(@"Excute block 2:%p",[NSThread currentThread]); 18 }); 19 dispatch_barrier_async(queue, ^{ 20 NSLog(@"Excute block 3:%p",[NSThread currentThread]); 21 [NSThread sleepForTimeInterval:4]; 22 }); 23 dispatch_async(queue, ^{ 24 NSLog(@"Excute block 4:%p",[NSThread currentThread]); 25 }); 26 } 27 打印结果: 28 2015-06-09 23:16:33.799 testGCD[46920:3369866] main thread:0x7f87f8c0af70 29 2015-06-09 23:16:33.800 testGCD[46920:3369866] current iOS Version:8.3 30 2015-06-09 23:16:33.800 testGCD[46920:3370037] Excute block 4:0x7f87f8e14a60 31 2015-06-09 23:16:33.800 testGCD[46920:3370029] Excute block 3:0x7f87f8f222d0 32 2015-06-09 23:16:35.802 testGCD[46920:3370027] Excute block 1:0x7f87f8f27a90 33 2015-06-09 23:16:36.804 testGCD[46920:3370026] Excute block 2:0x7f87f8c1e610
从打印结果可以看到不是预想的block3在block1、block2后面,最后再执行block4,说明在global_queue下dispatch_barrier_async失效。
2、当dispatch queue是用DISPATCH_QUEUE_CONCURRENT属性创建的queue时,dispatch_barrier_async有效:
1 - (void)testBarrierBlockWithCreateQueue 2 { 3 NSLog(@"current iOS Version:%.1f",[[[UIDevice currentDevice] systemVersion] floatValue]); 4 dispatch_queue_t queue = dispatch_queue_create("com.testBarrierGCD", DISPATCH_QUEUE_CONCURRENT); 5 dispatch_async(queue, ^{ 6 [NSThread sleepForTimeInterval:2]; 7 NSLog(@"Excute block 1:%p",[NSThread currentThread]); 8 }); 9 dispatch_async(queue, ^{ 10 [NSThread sleepForTimeInterval:3]; 11 NSLog(@"Excute block 2:%p",[NSThread currentThread]); 12 }); 13 dispatch_barrier_async(queue, ^{ 14 NSLog(@"Excute block 3:%p",[NSThread currentThread]); 15 [NSThread sleepForTimeInterval:4]; 16 }); 17 dispatch_async(queue, ^{ 18 NSLog(@"Excute block 4:%p",[NSThread currentThread]); 19 }); 20 } 21 打印结果: 22 2015-06-09 23:21:55.671 testGCD[46963:3373180] main thread:0x7fa51a428130 23 2015-06-09 23:21:55.672 testGCD[46963:3373180] current iOS Version:8.3 24 2015-06-09 23:21:57.676 testGCD[46963:3373293] Excute block 1:0x7fa51a65a890 25 2015-06-09 23:21:58.673 testGCD[46963:3373294] Excute block 2:0x7fa51a71cf50 26 2015-06-09 23:21:58.674 testGCD[46963:3373294] Excute block 3:0x7fa51a71cf50 27 2015-06-09 23:22:02.676 testGCD[46963:3373294] Excute block 4:0x7fa51a71cf50
从打印结果可以看出block执行顺序是按照我们预期的顺序在执行,至此说明了dispatch_barrier_async适用的场景是dispatch queue必须是用DISPATCH_QUEUE_CONCURRENT属性创建的queue(其实Apple文档中有说明的,以后用新的API时一定得仔细阅读文档,避免多走弯路)~祝大家玩的愉快~
测试代码已上传至GitHub:https://github.com/iOSGeek0829/testGCDWithBarrierBlock