考察点
-
1、请问打印顺序是什么?
```objectivec
(void)test1 { dispatch_queue_t queue = dispatch_queue_create(“conqueue”, DISPATCH_QUEUE_CONCURRENT); NSLog(@”1”); dispatch_async(queue, ^{
NSLog(@"2");
dispatch_async(queue, ^{
NSLog(@"3");
});
NSLog(@"4");
}); NSLog(@”5”); }
——————————- 结果出现随机情况 ——————————————-
打印顺序为:1,2,4,3,5;
2020-12-26 14:00:53.955684+0800 dd[20204:5183464] 1 2020-12-26 14:00:53.955978+0800 dd[20204:5183566] 2 2020-12-26 14:00:53.956161+0800 dd[20204:5183566] 4 2020-12-26 14:00:53.956200+0800 dd[20204:5183565] 3 2020-12-26 14:00:53.957317+0800 dd[20204:5183464] 5
打印顺序为:1,5,2,4,3;
2020-12-26 14:23:43.114659+0800 dd[20533:5200637] 1 2020-12-26 14:23:43.114890+0800 dd[20533:5200637] 5 2020-12-26 14:23:43.114918+0800 dd[20533:5200691] 2 2020-12-26 14:23:43.115101+0800 dd[20533:5200691] 4 2020-12-26 14:23:43.115122+0800 dd[20533:5200692] 3
**网上的都统一答案就是****:1,5,2,4,3;**<br />**实验结果:打印顺序不一定,也就是说,这一系列的相似的都是一个不太严谨的面试题?**<br />**<br />**结果:1,5,2,4,3;**
- **1、打印1**
- 2、往queue添加block任务,由于是异步方式,不需要等队列中的任务执行完成,继续执行下一部分代码;
- **3、打印5**
- 4、某个时刻CPU从线程池中调度之前异步创建的子线程,并从queue队列调度执行block任务
- **5、打印2**
- 6、同理,往queue添加block任务,由于是异步方式,不需要等队列中的任务执行完成,继续执行下一部分代码;
- **7、打印4**
- 8、某个时刻CPU从线程池中调度之前异步创建的子线程,并从queue队列调度执行block任务
- **9、打印3**
**<br />**结果:1,2,4,3,5;**
- CPU调度主线程,打印1
- CPU调度了子线程,执行queue中的任务,打印2,添加block任务到queue中,4,再执行之前添加的block任务,打印3
- CPU调度主线程,打印5
---
<a name="AFwpZ"></a>
# 2、请问打印顺序是什么?**
```objectivec
- (void)test1 {
dispatch_queue_t queue = dispatch_queue_create("conqueue", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"1");
dispatch_async(queue, ^{
NSLog(@"2%@",[NSThread currentThread]);
NSLog(@"2");
dispatch_async(queue, ^{
NSLog(@"3");
NSLog(@"3%@",[NSThread currentThread]);
});
NSLog(@"4");
});
NSLog(@"5");
NSLog(@"5%@",[NSThread currentThread]);
}
结果
出现随机情况1:
2020-12-26 14:12:16.206576+0800 dd[20404:5192295] 1
2020-12-26 14:12:16.206823+0800 dd[20404:5192295] 5
2020-12-26 14:12:16.207041+0800 dd[20404:5192295] 5<NSThread: 0x600000b98180>{number = 1, name = main}
2020-12-26 14:12:16.206903+0800 dd[20404:5192387] 2<NSThread: 0x600000bd6600>{number = 6, name = (null)}
2020-12-26 14:12:16.207677+0800 dd[20404:5192387] 2
2020-12-26 14:12:16.207817+0800 dd[20404:5192387] 4
2020-12-26 14:12:16.207902+0800 dd[20404:5192389] 3
2020-12-26 14:12:16.210616+0800 dd[20404:5192389] 3<NSThread: 0x600000bd5fc0>{number = 4, name = (null)}
结果
出现随机情况2:
2020-12-26 14:17:18.514383+0800 dd[20453:5195161] 1
2020-12-26 14:17:18.514921+0800 dd[20453:5195252] 2<NSThread: 0x6000031e5540>{number = 3, name = (null)}
2020-12-26 14:17:18.515334+0800 dd[20453:5195252] 2
2020-12-26 14:17:18.515520+0800 dd[20453:5195252] 4
2020-12-26 14:17:18.515616+0800 dd[20453:5195253] 3
2020-12-26 14:17:18.515851+0800 dd[20453:5195253] 3<NSThread: 0x6000031e4000>{number = 5, name = (null)}
2020-12-26 14:17:18.514742+0800 dd[20453:5195161] 5
2020-12-26 14:17:18.518071+0800 dd[20453:5195161] 5<NSThread: 0x6000031a42c0>{number = 1, name = main}
通过实例来证明,还是会出现多个随机结果
思考
这里涉及到了许多相关的多线程的概念
- CPU调度线程,线程池,主线程,子线程,线程状态切换等
- 主队列,串行队列,并发队列,队列特点(FIFO),block任务
- CPU异步执行任务等等
这种面试题的表现形式在工程中出现不可控的现象,不能这样用,假如真的期望执行结果存在先后顺序的话,可以考虑用信号量或者NSOperation的依赖来实现;