如何理解nodejs单线程

老实说,Node.js 非常有趣。
当JavaScript代码运行时,实际上只有一个线程。
您编写的代码必须在该线程中执行。

比如,如果你使用fs.readFile来读取一个文件,你认为你需要等待吗?不等了。
Node.js 将此任务留给 libuv 库,并继续自行执行其他任务。
这就是为什么它被称为非阻塞,你知道吗?
libuv是一个非常重要的库。
它有一个线程池,默认有四个线程。
它调度这四个线程去做文件读写、DNS检查等工作。
工作完成后我告诉你,主线程会继续使用事件循环来处理。

事件循环基于系统级多路复用。
Linux使用epoll,windows使用iocp。
它不盲目投票,效率很高。

看文件读取,流程如下:你的js调用fs.readFile,Node.js通过C++部分将任务传递给libuv,libuv找到一个线程来读取文件。
读取文件后,结果被放入队列中。
事件循环发现机会并在主线程中运行回调,并返回结果。

为什么说单线程?因为JS一次只能做一件事。
如果你写了一个无限循环什么的,整个事件循环就会卡住。
这是它的缺点。

但幸运的是,Node.js 很聪明,使用 libuv 的线程池来处理 I/O。
无需为每个I/O打开一个新线程,节省资金有储蓄。

如果从事大规模计算之类的CPU密集型任务,单个线程将无法处理。
要实现一些多线程,您必须使用工作线程或子进程。
它非常适合 I/O 密集型任务,异步 I/O 的效果令人惊叹。
例如,它特别适合网络服务器。

简而言之:单线程是JS执行环境,主线程依赖于事件循环。
非阻塞 I/O 依赖于 libuv 的线程池和事件循环。
这种设计非常适合I/O密集型应用,但对于CPU密集型应用要注意优化。

nodejs多线程还是单线程

2 02 2 年,我所在的城市有一个项目使用Node.js作为后端。
一开始以为单线程就可以了,后来发现处理大量数据的时候,呃,真是卡住了。
我当时就很困惑,怎么会发生这样的事情呢?后来仔细研究了一下,发现Node.js虽然只有一个主线程,但是其底层机制却很强大。
它将 I/O 操作留给内核,并且它自己的主线程忙于 JavaScript。
这称为事件循环,听起来很奇特。

后来我才知道,Node.js其实是用了多线程,比如文件读写、网络请求,都是由单独的线程来处理的。
它还有一个libuv库,可以自动创建线程池来处理高并发I/O任务,功能相当强大。

后来我发现Node.js有一个Cluster模块。
这个东西可以衍生子进程,每个子进程都可以独立运行。
这样不是可以分担主进程的压力吗?我在项目中使用了这个,效果很明显。
服务器响应速度得到了很大的提高。

但是,Node.js毕竟是单线程的,所以它不擅长处理CPU密集型任务。
我当时很极端,认为这行不通。
后来我调整了心态,发现其实可以通过一些方法来优化。
例如,使用child_process.fork()创建子进程并分配计算任务。
再比如,Node.js 1 0.5 之后,有了WorkerThreads模块,可以在单个进程中创建多个线程,这对我来说是个好消息。

总之,Node.js虽然是单线程的,但是通过巧妙的设计实现了多线程的效果。
开发者必须根据实际情况选择合适的优化策略,才能充分发挥效益。
对于我来说,我现在对 Node.js 有了新的认识。
虽然有时还是有点卡住,但我已经学会了如何处理它。