GCD学习之dispatch_barrier_async

    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

原文地址:https://www.cnblogs.com/NerdFooProgrammer/p/4564961.html