本文代码运行环境系统:MacOS High SierraNode.js:10.3.0

Node.js是单线程的,那么Node.js启动后线程数是1?

答案:Node.js启动后线程数并不是1,以下面代码为例

const http = require('http');http.createServer((req, res) => {res.end('hello');
}).listen(8000, () => {console.log('server is listening: ' + 8000);
});

通过Mac实用工具 > 活动监视器可以查看进程的线程数其实是6

Node.js启动的线程数不为1,是因为线程池?

答案:线程数不为1,不是因为线程池,而是因为V8。Node.js启动后会创建V8实例,V8实例是多线程的,V8中的线程有:

  • 主线程:获取代码、编译执行
  • 编译线程:主线程执行的时候,可以优化代码
  • Profiler线程:记录哪些方法耗时,为优化提供支持
  • 其他线程:用于垃圾回收清除工作,因为是多个线程,所以可以并行清除

Node.js线程池是预先创建好的?

答案:并不是,线程池中的线程是按需创建的。

const http = require('http');
const fs = require('fs');http.createServer((req, res) => {fs.readFile('./c.js', () => {});res.end('hello');
}).listen(8000, () => {console.log('server is listening: ' + 8000);
});

上面代码启动后,线程数依然是6

通过ab模拟访问后

ab -n1000 -c20 'http://192.168.76.101:8000/'


线程数才变成了10。之所以为10,是因为线程池中线程的默认值是4。

异步IO都要占用线程池?

答案:并不是,网络IO不会占用线程池

const http = require('http');http.createServer((req, res) => {http.get('http://192.168.1.100');res.end('hello');
}).listen(8000, () => {console.log('server is listening: ' + 8000);
});

上面这段代码,使用ab压测

ab -n10000 -c20 'http://192.168.76.101:8000'

无论多少次访问都不会创建线程,线程数永远为6。

文件IO一定会占用线程池?

答案:并不是,*Sync会阻塞主线程所以不会占用线程池,另外fs.FSWatcher也不会占用线程池。

虽然官方文档里面提到了fs.FSWatcher,但是其实并不能直接调用,关于FSWatcher访问 StackOverflow上有一个相关的提问https://stackoverflow.com/questions/35115444/nodejs-fs-fswatcher

线程池只能用于异步IO?

答案:并不是,除了一些IO密集操作外,Node.js对一些CPU密集的操作也会放到线程池里面执行(Crypto、Zlib模块)

DNS查询也有可能占用线程池?

答案:是的,因为dns.lookup方法会涉及到读取本地文件(例如nsswitch.conf,resolv.conf 以及 /etc/hosts)。而dns.resolve方法就不会占用线程池,这也是lookup和resolve的区别所在。

所以下面的代码,其实是会占用线程池的,因为http.get在dns解析的时候默认使用的是lookup方法。

const http = require('http');http.createServer((req, res) => {http.get('http://bj.meituan.com');res.end('hello');
}).listen(8000, () => {console.log('server is listening: ' + 8000);
});

线程池只供Node.js核心模块内部使用?

答案:不是的,官方文档里面有如下描述

You can use the built-in Node Worker Pool by developing a C++ addon. On older versions of Node, build your C++ addon using NAN, and on newer versions use N-API. node-webworker-threads offers a JavaScript-only way to access Node's Worker Pool.

线程池内线程数可以为0吗,可以无限大吗?

答案:不可以为0,也不是无限大的。通过UV_THREADPOOL_SIZE可以修改线程池的线程数(默认为4),线程数最大值为128,最小值为1。

主线程任何时候都不会阻塞吗?

答案:不是的,主线程在特定的情况下是会阻塞的。Node.js的事件循环中有一个阶段是poll,poll阶段在特定情况下是会阻塞的。这就是下图服务启动起来没有任何用户请求的时候Event Loop执行一次的时间比有少量请求的时候还要长的原因。


图片来源:https://medium.com/the-node-j...

参考资料

https://nodejs.org/en/docs/gu...
https://medium.freecodecamp.o...
https://medium.com/the-node-j...
https://jsblog.insiderattack....

Node.js 线程你理解的可能是错的 1相关推荐

  1. Node.js 线程你理解的可能是错的

    本文代码运行环境 系统:MacOS High Sierra Node.js:10.3.0 复制代码 Node.js是单线程的,那么Node.js启动后线程数是1? 答案:Node.js启动后线程数并不 ...

  2. Node.js 、Newman安装配置及报错问题解决

    Node.js .Newman安装配置及报错问题解决 Node.js 下载: Node.js 安装包及源码下载地址为:https://nodejs.org/en/download/. 你可以根据不同平 ...

  3. 【Node.js】如何理解非阻塞I/O(详解)

    Node.js 想要学好 node ,必须要理解 node 的特性. node 有三大特性:单线程.非阻塞I/O.事件驱动 如果你已经深刻理解了这三大特性,会发现这三大特性其实说的是一个事,三者少一不 ...

  4. Node JS Buffer使用理解

    JavaScript 起初为浏览器而设计,没有读取或操作二进制数据流的机制.Buffer类的引入,则让NodeJS拥有操作文件流或网络二进制流的能力. Buffer基本概念 Buffer 对象的内存分 ...

  5. Node.js v17版本npm run dev 报错opensslErrorStack

    Node.js 17版本opensslErrorStack: [ 'error:03000086:digital envelope routines::initialization error' ] ...

  6. Node.js 连接 MySQL 插入 TEXT 类型报错问题

    由于开发需要存储大量文本(其实是一个结构化对象字符串),考虑到 char 以及 varchar 都不够大,所以打算用 TEXT 类型,顺便记一下 TEXT.MEDIUMTEXT 以及 LONGTEXT ...

  7. linux进程退出所有tcp数据才发送,深入理解Node.js 进程与线程(8000长文彻底搞懂)...

    前言 进程与线程是一个程序员的必知概念,面试经常被问及,但是一些文章内容只是讲讲理论知识,可能一些小伙伴并没有真的理解,在实际开发中应用也比较少.本篇文章除了介绍概念,通过Node.js 的角度讲解进 ...

  8. [译]理解Node.js事件驱动机制

    学习 Node.js 一定要理解的内容之一,文中主要涉及到了 EventEmitter 的使用和一些异步情况的处理,比较偏基础,值得一读. 大多数 Node.js 对象都依赖了 EventEmitte ...

  9. 创业笔记-Node.js入门之阻塞与非阻塞

    阻塞与非阻塞 正如此前所提到的,当在请求处理程序中包括非阻塞操作时就会出问题.但是,在说这之前,我们先来看看什么是阻塞操作. 我不想去解释"阻塞"和"非阻塞"的 ...

最新文章

  1. 用metfanzi识别文字
  2. 实在不好意思,最近写个项目,一直没时间来灌水
  3. 如何应対syn flood
  4. java注解封装默认值_Java注解默认值
  5. 递归用法之“海盗分赃难题”
  6. Java API —— Map接口
  7. InstallShield Build Error -1014: Cannot rename directory PATH to PATH\folder.Bak.
  8. 使用简单工厂模式demo
  9. 架构师未来性的基础:简单性
  10. SSE图像算法优化系列二十一:基于DCT变换图像去噪算法的进一步优化(100W像素30ms)。...
  11. MySQL常用函数,你真得看看!
  12. Githup高级搜索
  13. 关于python开发CRM系统
  14. NUC1657 All in All【字符串匹配】
  15. ets5怎么找到数据文件夹_如何对文件夹进行加密
  16. 《OpenGL编程指南》一1.2 初识OpenGL程序
  17. Discuz!模板解析语法
  18. 微服务Spring Boot 整合 Redis 实现好友关注 – Feed流实现推送到粉丝收件箱
  19. ESP8266+micropython+HCSR04 超声波测距传感器
  20. RK3399中IO域电压的选择

热门文章

  1. 【iOS开发】什么是Bundle,每个iOS应用实际上是一个Bundle
  2. c#与马扎克通讯_马扎克伺服报警
  3. MyBatis中Like语句使用方式
  4. MyBatis调用存储过程,含有返回结果集、return参数和output参数
  5. activeMQ 的kahadb存储引擎分析
  6. iOS开发使用UIKeyInput自定义密码输入框
  7. JS进阶篇--JS数组reduce()方法详解及高级技巧 1
  8. 《JavaScript忍者秘籍》——1.3 跨浏览器注意事项
  9. Grunt构建工具能做哪些事?
  10. Android版Cocos2d-X应用的AnySDK集成Admob管理库教程