前言:
今天在群里, 有个小伙伴问了一个问题, 他们和js交互的时候, 需要等待js的一个回调.
主线程调用一个网络请求, 然后要等网络请求的结果回来之后, 然后在return.
他说, 他们之前是根据runloop去回调添加监听解决的.说又引发了一些其他的问题, 问有没有人知道怎么做.
解决
我一直以为这应该是大部分都知道的, 直到他用runloop解决, 很多人都在群里讨论说没法实现, 我才意识到或许并不是那么简单.
方法一
如果你实在是不知道怎么解决, 那么就把return去掉换成block回调, 然后进行调用. 当然这可能会让你去重写一部分逻辑代码, 但是解决起来算是好用的.
方法二
就是在主线程做堵塞.那么问题来了
- 主线程可不可以做阻塞?
- 主线程调用async会不会开辟新线程?
主线程调用async会不会开辟新线程?
先说一个基础的async不管是同步队列, 还是异步队列, 调用async都会开辟线程, 但是区别是什么呢? 主线程async会吗?

建议先把图片放大, 自己思考一下会输出什么.
**1--<NSThread: 0x600001e08880>{number = 1, name = main}**
**3--<NSThread: 0x600001e5cc40>{number = 5, name = (null)}**
**2--<NSThread: 0x600001e08880>{number = 1, name = main}**
主线程异步调用不会开辟新线程, 但是主队列是一个串行队列, 任务异步加入之后一定是先执行完当前的任务, 才会去执行后面的任务.
自定义同步队列怎么打印?

先分析, 自定义同步队列:
- 在主线程调用, 所以1,4,5是在主线程. 1-4-5的顺序应该没有疑问
- 2和3的问题, 2任务是先添加在同步队列queue中, 所以2-3的顺序.
- 2任务不影响4的执行, 但是3任务阻塞了5任务的执行.
所以1-4-2-3-5其中2和4并不固定,1最前,3,5最后

所以, sync调用不会创建线程, 会在当前所在任务的线程, 并且对任务进行阻塞, 等待block_t中的任务执行完毕才继续进行当前所在任务.
自定义异步队列怎么打印?

分析一下:
根据上面的问题, 大概知道了任务在线程中跑的逻辑
- 首先可以确定,1-3-4-5是在主线程, 或者demo4在哪个线程调用就是哪个线程.
- 2的任务是异步队列, 异步执行, 在另一条线程中无拘无束.
所以最终的打印是:1-3-4-5, 2只在1之后的任意位置.

好东西:iOS面试资料大全
主线程阻塞解决方案
问题代码:

大概就是这么一个问题, 主线程调用了一个方法, 需要等web的回调. 然而, 主线程不能用信号量卡, 一卡就会卡死, 所以群里的人说runloop的解决要换掉, 有没有好用的方式.
可以先思考三秒, 这样打印可能是10也可能是15, 这都不一定, 但是大概率是10:
直接给出答案了, 因为我觉得多写写线程, 队列, 锁之类的这些都是常识性的东西, 并不是很难理解:

还有其他的实现方案, 这里只是提供一种思路, 如果看懂了, 其实还可以在想想其他的. 这也充分说明了,一个线程多个队列, 一个队列多个任务.
注意, 不可以在这里面去添加getMainQueue的sync的任务, 不然会任务相互堵塞, 我试用了, 我们项目的一个第三方, 他的请求内部调用了HUD所以这种的会直接任务相互卡, 界面就会卡死.
下图可以看出线程和队列的关系:

后续我会把GCD源码的重要点详细列出来.
总结
世界存在的意义不就是发现问题和解决问题吗, 所以遇见问题才是敲代码的意义.
推荐面试题文章:

本文讨论了在iOS开发中如何避免主线程阻塞,尤其是在等待网络请求回调时。文中提出了两种方法:使用block回调重写部分逻辑,以及理解GCD中async和sync在主线程上的行为。通过分析同步队列和异步队列的工作原理,解释了主线程异步调用不会开辟新线程,而sync调用会在当前线程上阻塞。同时提醒开发者避免在主线程上使用可能导致阻塞的操作,以防止界面卡死。
536

被折叠的 条评论
为什么被折叠?



