nodejs非阻塞单线程架构,noejs事件循环

nodejs非阻塞单线程架构,noejs事件循环
最新回答
朕就是萌萌哒

2022-06-20 04:43:28

Node.js 的非阻塞单线程架构和事件循环是其高性能的关键特性。以下是对这些概念的详细解释,并结合提供的代码示例进行分析:

一、Node.js 非阻塞单线程架构
  1. 单线程:Node.js 的主线程是单线程的,负责处理 JavaScript 代码的执行。这意味着所有的同步代码都在同一个线程中执行,避免了多线程环境下的锁和同步问题。

  2. 非阻塞 I/O:Node.js 通过事件循环和线程池实现非阻塞 I/O 操作。当遇到 I/O 操作(如文件读写、网络请求等)时,Node.js 会将这些操作交给线程池处理,主线程继续执行后续代码,不会等待 I/O 操作完成。

  3. 事件驱动:Node.js 使用事件驱动模型,通过事件循环来处理异步操作的结果。当 I/O 操作完成时,线程池会将结果通过回调函数或 Promise 返回给主线程,主线程在事件循环中处理这些结果。

二、Node.js 事件循环

事件循环是 Node.js 处理异步操作的核心机制,它分为以下几个阶段:

  1. Timers(定时器阶段):处理 setTimeout 和 setInterval 的回调函数。
  2. Pending I/O callbacks(待定 I/O 回调阶段):处理系统操作(如 TCP 错误)的回调函数。
  3. Idle/Prepare(空闲/准备阶段):内部使用。
  4. Poll(轮询阶段)

    检索新的 I/O 事件。

    执行与 I/O 相关的回调(除了 setTimeout、setInterval、setImmediate 的回调)。

    如果队列为空,检查是否有 setImmediate 的回调需要执行。如果有,进入下一个阶段;如果没有,则等待新的 I/O 事件。

  5. Check(检查阶段):处理 setImmediate 的回调函数。
  6. Close callbacks(关闭回调阶段):处理 socket.on('close', ...) 等关闭事件的回调函数。
三、代码示例分析

提供的代码示例展示了 Node.js 的事件循环和异步操作:

  1. cpuFocus 函数

    模拟 CPU 密集型计算,通过 Array.map 进行大量随机数生成。

    使用 setImmediate 将部分计算任务推迟到事件循环的检查阶段执行。

    由于是同步代码,会阻塞主线程,导致 timer 的输出被延迟。

  2. ioFocus 函数

    模拟 I/O 密集型操作,使用 await sleep(基于 setTimeout 的 Promise 化)进行异步等待。

    通过 setImmediate 将后续的异步操作推迟到事件循环的检查阶段执行。

    由于是异步操作,不会阻塞主线程,timer 的输出会正常进行。

  3. timer 函数

    使用 setInterval 每秒输出一次当前秒数。

    如果 second 达到 num(默认为 10),则清除定时器。

四、运行结果分析
  • testmode = 1(I/O 测试)

    ioFocus 的异步操作不会阻塞主线程,timer 的输出会正常进行。

    输出顺序:timer 的秒数输出和 ioFocus 的异步日志会交替出现。

  • testmode = 2(CPU 测试)

    cpuFocus 的同步计算会阻塞主线程,timer 的输出会被延迟。

    输出顺序:先完成所有同步计算,然后输出 timer 的剩余秒数。

  • testmode = 3 或 4(I/O + CPU 测试)

    结合了 I/O 和 CPU 操作的行为,具体输出顺序取决于两者的执行顺序和事件循环的调度。

五、总结
  • Node.js 的单线程架构通过事件循环和非阻塞 I/O 实现了高性能。
  • 同步代码会阻塞主线程,异步代码(如 setTimeout、setImmediate、Promise)不会阻塞主线程。
  • 事件循环的各个阶段按顺序执行,确保异步操作的结果被正确处理。
  • 合理使用异步操作可以避免主线程阻塞,提高应用的并发性能。