- 首先我想先总结一下函数调用时的 阻塞与非阻塞;同步与异步。
是否同步主要是看两个函数是否相互依赖;如果 funcA 调用 funcB 后,funcA 后续代码只有在 funcB 执行完毕才会继续执行,那么就是同步的;否则 funcA 和 funcB 可以相互独立,那就是异步的。
具体同步来说, funcA 和 funcB 是同步的,它俩既可以在同一个线程中执行,也可以在不同线程中执行。在不同线程中执行就是 IO 请求的情况,调用线程会因文件读取而被操作系统暂停运行,而这也是一种阻塞式IO。
具体异步来说,如果调用方需要知道函数的执行结果,那么可以通过 通知 或者 回调函数 两种方法实现。
而是否阻塞的判断主要来自:funcA 调用 funcB 时,funcA 所在的线程/进程是否因调用 funcB 而被操作系统挂起而暂停运行。 如果被挂起暂停运行了,那么就是阻塞式调用。
那么非阻塞式调用是否就一定是异步的呢?不是的。虽然 funcA 所在线程/进程并没有被 funcB 阻塞,但是 funcA 在 funcB 执行过程中可以选择不继续执行 funcB 后续的语句,而是不停的询问。
(参考 陆小风大佬著《计算机底层的秘密》,书特别好,给人带来很多启发!!)
- 进程的资源分配。线程共享了哪些资源,为什么需要信息交换? 线程之间共享代码段、数据段、堆、文件打开描述符、拥有相同的Pid(代表它们属于同一个进程);有属于其本身的不共享的 isolated 堆段(保存 function calls 和 local variables)
- ArkTS 中的线程
ArkTS 是同 typescript 也是单线程模型,采用轮询机制, 主线程在空闲时再去执行微任务队列和宏任务队列中的任务。只有在微任务队列中的任务全部执行完后,才会去执行宏任务队列中的任务。(即使宏任务队列中的 setTimeout 时间设置为 0ms, 依旧是等微任务队列中的任务全部执行完后才会轮到它)
微任务队列:Promise.then(),Promise.catch(),Multation.Observer();比如 resolve(参数) 会将这个参数值传递给 Promise.then();触发后不会立即执行 .then() 中的回调,而是将其放于微任务队列。
宏任务队列:setTimeout(),setInterval(),I/O操作;
可以使用 Node.js 提供的 Worker Thread 机制将一些比较复杂的计算放到 worker 线程中。