为什么说 Node.js 是单线程的?
一般人理解 Node 是单线程的,所以 Node 启动后线程数应该为 1,我们做实验看一下。
setInterval(() => {
console.log(new Date().getTime())
}, 3000)
可以看到 Node 进程占用了 7 个线程(注意:不同版本 node 占用的线程数可能不一致)。为什么会有 7 个线程呢?
我们都知道,Node 中最核心的是 V8 引擎,在 Node 启动后,会创建 V8 实例,这个实例是多线程的。
- 主线程:编译、执行代码。
- 编译/优化线程:在主线程执行的时候,可以优化代码。
- 分析器线程:记录分析代码运行时间,为 Crankshaft 优化代码执行提供依据。
- 垃圾回收的几个线程。
所以大家常说的 Node 是单线程的指的是 JavaScript 的执行是单线程的,但 Javascript 的宿主环境,无论是 Node 还是浏览器都是多线程的。
为什么 Node.js 不适合 CPU 密集型操作,适合 I/O 密集型操作?
Node 适合 I/O 密集型操作,是因为 V8 通过 Node api (c++ 接口) 将 I/O 等异步任务交给了 libuv 线程池里的线程来完成,不会阻塞主线程执行。而你的 JS 运算代码(CPU 密集型操作),是无法交给 libuv 里的线程来处理的,只能运行在主线程,运算量过大就会阻塞主线程后续代码,当然 NodeJs 也可以通过 cluster / child_process / work_threads 等方式,启用多进程/多线程来处理 CPU 密集型的任务,但相比其它成熟的方案并没有优势。
exports & module.exports 的区别?
exports = module.exports = {},exports 只是 module.exports 的引用,require 引入的是 module.exports 对应的对象。为了避免糊涂,尽量都用 module.exports 导出。
exports.name = 'Alan';
exports.test = function () {
console.log('hi')
};
console.log(module) // module: { exports: { name: 'Alan', test: [Function] } }
// exports 初始值是 module.exports 的引用,可以给它赋值另一个对象,但不会修改导出的对象
exports = {
name: 'Bob',
add: function (a, b) {
return a + b;
}
}
console.log(exports) // { name: 'Bob', add: [Function] }
console.log(module) // module: { exports: { name: 'Alan', test: [Function] } }
cluster / child_process / work_threads 的区别?
Node 中提供了 cluster 模块,cluster 实现了对 child_process 的封装,通过 fork 方法创建子进程的方式实现了多进程模型,无论 child_process 还是 cluster,都不是多线程模型,而是多进程模型。
Node 10.5.0 的发布,官方才给出了一个实验性质的模块 worker_threads 给 Node 提供真正的多线程能力。
链接
以下链接是我最近学 Node.js 觉得还不错的: