Node.js 是单线程的,但它可以通过以下方式有效地利用计算机的 CPU 资源:
1. 异步 I/O 操作
- 概念:Node.js 使用异步非阻塞 I/O 操作,这意味着它在等待 I/O 操作(如文件读写、网络请求)完成时不会阻塞主线程。
- 实现:Node.js 的异步 I/O 操作由底层的 libuv 库管理,libuv 使用线程池来处理这些 I/O 操作。当 I/O 操作完成后,回调函数会被触发,主线程继续执行其他任务。
2. 事件循环(Event Loop)
- 概念:事件循环是 Node.js 的核心机制,它管理异步操作的执行。事件循环不断检查事件队列并执行相应的回调函数。
- 实现:事件循环使得 Node.js 能够在处理 I/O 操作时继续处理其他任务,而不是阻塞线程等待 I/O 完成。
3. libuv 线程池
- 概念:libuv 是 Node.js 的底层库,提供了跨平台的异步 I/O 操作。它内部包含一个线程池,用于处理一些需要阻塞的操作(如文件系统操作、DNS 查询等)。
- 实现:libuv 线程池允许 Node.js 在进行这些阻塞操作时,不影响主线程的运行。线程池的任务完成后,结果会被传递回事件循环中的回调函数。
4. Worker Threads
- 概念:Node.js 也提供了
worker_threads
模块,可以在多线程环境中运行 JavaScript 代码。 - 实现:通过
worker_threads
,Node.js 可以创建多个线程,这些线程可以并行地处理计算密集型任务,而主线程继续处理事件循环。这使得 Node.js 能够利用多核 CPU 的能力。
5. Cluster 模块
- 概念:Node.js 的
cluster
模块允许创建多个进程,每个进程都有自己的事件循环和内存空间,但它们可以共享端口和负载均衡。 - 实现:使用
cluster
模块,可以充分利用多核 CPU。每个子进程(工作进程)处理不同的请求,而主进程负责负载均衡和管理。