今天我们讲解几道这两天遇到的面试题--GCD编程的.题目很不错,很考究关于GCD的基本概念和使用.
对于基本的概念,本人博客已在前面讲过,本篇主要以面试题来讲解.大家可看一下本人关于GCD的基本讲解 https://www.cnblogs.com/guohai-stronger/p/9038567.html
GCD编程的核心就是dispatch队列, dispatch block的执行都会最终放到某个队列中执行.我们直接以题目来讲解:
【例1】GCD面试题1
- (void)viewDidLoad { [super viewDidLoad]; [self testGCD]; } - (void)testGCD { //并行队列 dispatch_queue_t queue = dispatch_queue_create("zxy", DISPATCH_QUEUE_CONCURRENT); NSLog(@"1"); dispatch_async(queue, ^{ NSLog(@"2"); dispatch_async(queue, ^{ NSLog(@"3"); }); NSLog(@"4"); }); NSLog(@"5"); }
讲解:
- 首先看创建队列是并行队列,无需等待;
- 首先打印出 1 ,然后看dispatch_async,将dispatch_async代码段整个看做事物,对于并行队列,并不会等待,然后绕过dispatch_async事物,执行下面的内容,执行完下面内容后再次执行该事物;
- 紧接着打印出 5 ,执行完打印5,再次会执行dispatch_async整个代码段,看里面的内容有打印出 2 ,还有一个dispatch_async,还有打印出 4
NSLog(@"2"); dispatch_async(queue, ^{ NSLog(@"3"); }); NSLog(@"4");
- 又因为是dispatch_async,以及后面打印出 4 ,又是并行队列,异步执行,所以会先执行打印 4
- 执行完打印出 4 后,就会执行 3
验证结果截图:
【例2】GCD面试题2
- (void)viewDidLoad { [super viewDidLoad]; [self testGCD]; } - (void)testGCD { //串行队列 dispatch_queue_t queue = dispatch_queue_create("zxy", DISPATCH_QUEUE_SERIAL); NSLog(@"1"); dispatch_async(queue, ^{ NSLog(@"2"); dispatch_sync(queue, ^{ NSLog(@"3"); }); NSLog(@"4"); }); NSLog(@"5"); }
讲解:
- 首先是串行队列,只能按顺序执行
- 首先打印出 1 ,然后是dispatch_async会开启线程,里面的内容会慢些执行,执行下面的打印 5
- 打印出 5,然后回到dispatch_async里面,异步执行会开启线程,发现里面有NSLog(@“2”),dispatch_syncy是个同步执行,NSLog(@“4”),然后先打印出 2
- 因为外面dispatch_async,打印出2 之后,开始走 NSLog(@“4”),然后再回到同步里面NSLog(@“3”),然后我们发现dispatch_syncy是个同步执行,也就是不执行完同步里面的NSLog(@“3”),就不可能走NSLog(@“4”),所以说两边都在等着对方,造成了死锁。
- 在程序中会崩溃
验证结果截图:
【例3】GCD面试题3
dispatch_queue_t queue = dispatch_queue_create("zxy", DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue, ^{ NSLog(@"哈哈哈 1"); }); dispatch_async(queue, ^{ NSLog(@"哈哈哈 2"); }); dispatch_sync(queue, ^{ NSLog(@"哈哈哈 3"); });
//////////////////// NSLog(@"哈哈哈 0"); dispatch_async(queue, ^{ NSLog(@"哈哈哈 7"); }); dispatch_async(queue, ^{ NSLog(@"哈哈哈 8"); }); dispatch_async(queue, ^{ NSLog(@"哈哈哈 9"); });
A 1230789 B 1237890 C 3120798 D 2137890 C 3012789
上面五种答案,哪一个是对的?
讲解:
- 首先是并行队列 DISPATCH_QUEUE_CONCURRENT,可以并行的执行任务
- 在哈哈哈 3中是同步执行,所以此后面的代码在3没有执行完之前是不可能执行的,而前面的哈哈哈 1 和哈哈哈 2都是异步,是可以执行完的,但是当哈哈哈3执行完会紧接着执行 哈哈哈0,所以不可能出现7,8,9在0之前执行完
- 从上可以判断出 A C E 是可能出现的
将上面的代码运行到xcode得到如下:E答案
【例4】GCD面试题4
我们将DISPATCH_QUEUE_CONCURRENT改为DISPATCH_QUEUE_SERIAL
因为将并行队列改为串行队列,所有任务按部就班执行,所以结果如下(不加以讲解)
【例5】GCD面试题5
- (void) testGCD{ __block NSInteger a = 0; while (a < 100) { dispatch_async(dispatch_get_global_queue(0, 0), ^{ a++; NSLog(@"%ld======%@", a, [NSThread currentThread]); }); } NSLog(@"卧槽无情%ld", a); }
讲解:
- 首先不可能打印出0,因为有while循环,while不走完,是不可能走后面的.a = 0, 然后进入while循环, 因为是异步,所以就会开启线程执行a ++ , 可能开出的线程状态不好,所以a可能继续为0, ……
- 但是在某个时刻,可能线程64状态返回,执行a++, 所以a = 1 ,……
- 所以a的最后值是大于等于100(>=100)
可能状态还不错,从上面看出结果为100
拓展 下面有几道同样的类似GCD面试题目,结果给大家,大家自己体会
【例6】GCD面试题6
- (void) testGCD2 { dispatch_queue_t queue = dispatch_queue_create("zxy", DISPATCH_QUEUE_CONCURRENT); NSLog(@"1"); dispatch_async(queue, ^{ NSLog(@"2"); dispatch_sync(queue, ^{ NSLog(@"3"); }); NSLog(@"4"); }); NSLog(@"5"); }
结果如下:
【例7】GCD面试题7
- (void) testGCD2 { dispatch_queue_t queue = dispatch_queue_create("zxy", DISPATCH_QUEUE_CONCURRENT); NSLog(@"1"); dispatch_async(queue, ^{ NSLog(@"2"); dispatch_async(queue, ^{ NSLog(@"3"); }); NSLog(@"4"); }); NSLog(@"5"); }
结果如下:
【例8】GCD面试题8
- (void) testGCD2 { dispatch_queue_t queue = dispatch_queue_create("zxy", DISPATCH_QUEUE_SERIAL); NSLog(@"1"); dispatch_async(queue, ^{ NSLog(@"2"); dispatch_async(queue, ^{ NSLog(@"3"); }); NSLog(@"4"); }); NSLog(@"5"); }
结果如下:
以上就是GCD的经典面试题,其实看了这几道面试题,发现还都是GCD的基本内容,串行队列,并行队列,以及同步异步是否开启线程的基本概念,希望通过本次讲解,大家对GCD的认识会更上一层,谢谢!!!