考察点

  • 并发队列 + 异步执行方式 对执行顺序的影响

    1、请问打印顺序是什么?

    ```objectivec

  • (void)test1 { dispatch_queue_t queue = dispatch_queue_create(“conqueue”, DISPATCH_QUEUE_CONCURRENT); NSLog(@”1”); dispatch_async(queue, ^{

    1. NSLog(@"2");
    2. dispatch_async(queue, ^{
    3. NSLog(@"3");
    4. });
    5. 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. **网上的都统一答案就是****:15243;**<br />**实验结果:打印顺序不一定,也就是说,这一系列的相似的都是一个不太严谨的面试题?**<br />**<br />**结果:15243;**
  2. - **1、打印1**
  3. - 2、往queue添加block任务,由于是异步方式,不需要等队列中的任务执行完成,继续执行下一部分代码;
  4. - **3、打印5**
  5. - 4、某个时刻CPU从线程池中调度之前异步创建的子线程,并从queue队列调度执行block任务
  6. - **5、打印2**
  7. - 6、同理,往queue添加block任务,由于是异步方式,不需要等队列中的任务执行完成,继续执行下一部分代码;
  8. - **7、打印4**
  9. - 8、某个时刻CPU从线程池中调度之前异步创建的子线程,并从queue队列调度执行block任务
  10. - **9、打印3**
  11. **<br />**结果:12435;**
  12. - CPU调度主线程,打印1
  13. - CPU调度了子线程,执行queue中的任务,打印2,添加block任务到queue中,4,再执行之前添加的block任务,打印3
  14. - CPU调度主线程,打印5
  15. ---
  16. <a name="AFwpZ"></a>
  17. # 2、请问打印顺序是什么?**
  18. ```objectivec
  19. - (void)test1 {
  20. dispatch_queue_t queue = dispatch_queue_create("conqueue", DISPATCH_QUEUE_CONCURRENT);
  21. NSLog(@"1");
  22. dispatch_async(queue, ^{
  23. NSLog(@"2%@",[NSThread currentThread]);
  24. NSLog(@"2");
  25. dispatch_async(queue, ^{
  26. NSLog(@"3");
  27. NSLog(@"3%@",[NSThread currentThread]);
  28. });
  29. NSLog(@"4");
  30. });
  31. NSLog(@"5");
  32. NSLog(@"5%@",[NSThread currentThread]);
  33. }
  34. 结果
  35. 出现随机情况1:
  36. 2020-12-26 14:12:16.206576+0800 dd[20404:5192295] 1
  37. 2020-12-26 14:12:16.206823+0800 dd[20404:5192295] 5
  38. 2020-12-26 14:12:16.207041+0800 dd[20404:5192295] 5<NSThread: 0x600000b98180>{number = 1, name = main}
  39. 2020-12-26 14:12:16.206903+0800 dd[20404:5192387] 2<NSThread: 0x600000bd6600>{number = 6, name = (null)}
  40. 2020-12-26 14:12:16.207677+0800 dd[20404:5192387] 2
  41. 2020-12-26 14:12:16.207817+0800 dd[20404:5192387] 4
  42. 2020-12-26 14:12:16.207902+0800 dd[20404:5192389] 3
  43. 2020-12-26 14:12:16.210616+0800 dd[20404:5192389] 3<NSThread: 0x600000bd5fc0>{number = 4, name = (null)}
  44. 结果
  45. 出现随机情况2:
  46. 2020-12-26 14:17:18.514383+0800 dd[20453:5195161] 1
  47. 2020-12-26 14:17:18.514921+0800 dd[20453:5195252] 2<NSThread: 0x6000031e5540>{number = 3, name = (null)}
  48. 2020-12-26 14:17:18.515334+0800 dd[20453:5195252] 2
  49. 2020-12-26 14:17:18.515520+0800 dd[20453:5195252] 4
  50. 2020-12-26 14:17:18.515616+0800 dd[20453:5195253] 3
  51. 2020-12-26 14:17:18.515851+0800 dd[20453:5195253] 3<NSThread: 0x6000031e4000>{number = 5, name = (null)}
  52. 2020-12-26 14:17:18.514742+0800 dd[20453:5195161] 5
  53. 2020-12-26 14:17:18.518071+0800 dd[20453:5195161] 5<NSThread: 0x6000031a42c0>{number = 1, name = main}

通过实例来证明,还是会出现多个随机结果

思考

这里涉及到了许多相关的多线程的概念

  • CPU调度线程,线程池,主线程,子线程,线程状态切换等
  • 主队列,串行队列,并发队列,队列特点(FIFO),block任务
  • CPU异步执行任务等等

这种面试题的表现形式在工程中出现不可控的现象,不能这样用,假如真的期望执行结果存在先后顺序的话,可以考虑用信号量或者NSOperation的依赖来实现;