专栏首页程序员成长指北你觉得Node.js是单线程这个结论对吗?

你觉得Node.js是单线程这个结论对吗?

前言

一提到 Node.js ,我想大家都会想到它的一个特点,单线程。但是 Node.js 在运行的时候依赖 V8 这个宿主环境,难道在宿主环境中也是单线程吗?请看正文解释你这个疑惑。

Node.js 单线程误区

开启 Node.js 服务 Demo

const http = require('http');

const server = http.createServer();
server.listen(3000,()=>{
    process.title='程序员成长指北测试进程';
    console.log('进程id',process.pid)
})

看这段代码,创建了 http 服务,开启了一个进程,都说了 Node.js 是单线程,所以 Node.js 启动后线程数应该为 1,但是事实并非如此,呜呜呜。

看活动监视器怎么开启7个线程呢?难道Javascript不是单线程不知道小伙伴们有没有这个疑问?

解释一下这个原因:

Node.js 中最核心的是 V8 引擎,在 Node.js 启动后,会创建 V8 的实例,这个实例是多线程的。

  • 主线程:编译、执行代码。
  • 编译/优化线程:在主线程执行的时候,可以优化代码。
  • 分析器线程:记录分析代码运行时间,为 Crankshaft 优化代码执行提供依据。
  • 垃圾回收的几个线程。

所以大家常说的 Node.js 是单线程的指的是 JavaScript 的执行是单线程的(开发者编写的代码运行在单线程环境中),但 Javascript 的宿主环境,无论是 Node 还是浏览器都是多线程的因为 libuv 中有线程池的概念存在的,libuv 会通过类似线程池的实现来模拟不同操作系统的异步调用,这对开发者来说是不可见的。

V8中什么时候会创建额外进程

某些异步 IO 会占用额外的线程

还是上面那个例子,我们在定时器执行的同时,去读一个文件:

const fs = require('fs')
setInterval(() => {
    console.log(new Date().getTime())
}, 3000)

fs.readFile('./kaola.html', () => {})

线程数量变成了 11 个,这是因为在 Node 中有一些 IO 操作(DNS,FS)和一些 CPU 密集计算(Zlib,Crypto)会启用 Node 的线程池,而线程池默认大小为 4,因为线程数变成了 11。

手动更改线程池默认大小:

process.env.UV_THREADPOOL_SIZE = 64

修改线程池默认大小后,轻松把线程变成 71。

Libuv

Libuv 是一个跨平台的异步 IO 库,它结合了 UNIX 下的 libev 和 Windows 下的 IOCP 的特性,最早由 Node.js 的作者开发,专门为 Node.js 提供多平台下的异步IO支持。Libuv 本身是由 C++ 语言实现的,Node.js 中的非阻塞 IO 以及事件循环的底层机制都是由 libuv 实现的。

libuv架构图

在 Windows 环境下,libuv 直接使用Windows的 IOCP 来实现异步IO。在 非Windows 环境下,libuv使用多线程(线程池Thread Pool)来模拟异步IO,这里仅简要提一下 libuv 中有线程池的概念,之后的文章会介绍 libuv 如何实现进程间通信。

注意下面我要说的话:

Node的异步调用是由 libuv 来支持的,以上面的读取文件的例子,读文件实质的系统调用是由 libuv 来完成的,Node只是负责调用 libuv 的接口,等数据返回后再执行对应的回调方法。

总结

本篇文章仅对 Node.js 的单线程误区做了讲解,不过本篇文章只是 Node.js 高级进阶之进程与线程的 预热篇,接下来的文章会 对 Node.js 的进程与线程做一个详细讲解,包括原理分析,child_process 模块与 cluster模块,进程守护以及在真实项目中的 Node.js 多进程架构模型等内容。

来,告诉你Node.js究竟是什么?

Node.js 高级进阶之 fs 文件模块学习

说Node.js做后端开发,stream有必要了解下

深入理解Javacript从作用域作用域链开始

【JS必知必会】高阶函数详解与实战

交流学习

大家好,我是koala,公众号「程序员成长指北」作者。目前在做一个 Node.js 工程师高级进阶路线,加入我们一起学习吧!

本文分享自微信公众号 - 程序员成长指北(coder_growth)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-08-05

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 安装jdk

    吟风者
  • 大侠,请留步,要进来了解一下 python 由来?

    每一门计算机语言的发展历史,都有一个有趣的故事。大神们的作品总是让人出乎意料,一言不合就创造出惊天动地的事情。要想了解python的由来,必须要追溯到ABC语言...

    公众号---志学Python
  • JVM - 运行时数据区域(1)

    Java 虚拟机在执行 Java 程序的过程中,会把它管理的内存划分成若干个不同的数据区域。

    happyJared
  • SoapUI系列|项目实战

    笔者工作中是项目api来源为jira-confluence,研发哥哥会把api接口的详细定义写到confluence上

    测试邦
  • 【JS】297-[译]正确使用 sort() 方法

    在过去的几个星期里,我们在不同的团队中看到,一般来说都没有使用 Array.prototype.sort()的习惯,并且不知道这种方法是如何工作的。今天我们将尝...

    pingan8787
  • Android实现可移动的悬浮窗

    我们在很多android应用中可能会看到悬浮窗按钮,最多的应该就是360了,通过代码我们也可以实现这个功能

    Vaccae
  • Android里AlertDialog多种使用方法及DEMO

    我们在使用Android的APP时经常会点击某个按钮弹出来选择的对话框提供选项,选择的对话框也可以分为多样,如确定取消类型,单选类型,复选类型,列表类型等.在A...

    Vaccae
  • Groovy 笔记

    Groovy 是基于 JVM 的 动态脚本语言,可以与 Java 无缝对接。Groovy 并不替代 Java,而是与 Java 互补

    tonglei0429
  • 当我们按下电源键,Android 究竟做了些什么?

    ? 现在,按下电源键 下面是Android启动的核心步骤流程图,看文字的时候,记得回来对照图来理解喔,希望阅读全文后,回观流程图,会有恍然大悟的感觉,那么...

    腾讯移动品质中心TMQ
  • 19年5月社招面试经验(六)

    上周三就结束了阿里的三面,这周每天都骚扰阿里的HR小姐姐什么时候给我安排交叉面,对方一直在说等面试官时间,没想到,刚刚突然给我来电话问我有没有空交叉面。

    晓痴

扫码关注云+社区

领取腾讯云代金券