主线程如何进行阻塞?
前言:
今天在群里, 有个小伙伴问了一个问题, 他们和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
之后的任意位置.
主线程阻塞解决方案
问题代码:
大概就是这么一个问题, 主线程调用了一个方法, 需要等
web
的回调. 然而, 主线程不能用信号量卡, 一卡就会卡死, 所以群里的人说runloop
的解决要换掉, 有没有好用的方式.
可以先思考三秒, 这样打印可能是10也可能是15, 这都不一定, 但是大概率是10:
直接给出答案了, 因为我觉得多写写线程, 队列, 锁之类的这些都是常识性的东西, 并不是很难理解:
还有其他的实现方案, 这里只是提供一种思路, 如果看懂了, 其实还可以在想想其他的.
这也充分说明了,一个线程多个队列, 一个队列多个任务.
注意, 不可以在这里面去添加
getMainQueue
的sync
的任务, 不然会任务相互堵塞, 我试用了, 我们项目的一个第三方, 他的请求内部调用了HUD
所以这种的会直接任务相互卡, 界面就会卡死.
下图可以看出线程和队列的关系:
后续我会把GCD源码的重要点详细列出来.
总结
世界存在的意义不就是发现问题和解决问题吗, 所以遇见问题才是敲代码的意义.
转载自:https://juejin.cn/post/6991269143475388446