node是多线程吗,node js 多线程

  node是多线程吗,node js 多线程

  为什么Node.js不是完全单线程的?怎么理解?下面这篇文章就带你探讨一下,希望能帮到你!

  node.js速度课程简介:进入学习

  相信大家都知道node是单线程程序,利用事件循环可以实现多个并发。不幸的是,这并不完全正确。

  那么Node.js为什么不是完全单线程的程序呢?

  

Node.js 是单线程的程序*

  我们自己所有的Javsacript,V8,EventLoop都运行在同一个线程里,也就是主thrad。

  哎,这不就是说node是单线程的吗?

  但是可能你不知道node里面有很多模块背后都是C代码。

  虽然node没有给用户控制线程的权限,但是C可以使用多线程。

  那么node什么时候会用多线程呢?

  如果一个节点方法调用后面C的同步方法,都是在主线程内部运行。

  如果一个节点方法调用了后面C的异步方法,有时它并不在主线程内部运行。

  

同步方法,跑在 main thread 里面

  这里的密码相关模块,很多都是c写的,下面这个程序是一个计算hash的函数,一般用来存储密码。

  从“crypto”导入{ pbk df 2 sync };

  const start time=date . now();

  设索引=0;

  for(索引=0;指数3;索引){

  pbkdf2Sync(秘密,盐,100000,64, sha 512 );

  const end time=date . now();

  console.log(`${index} time,$ { end time-start time } `);

  }

  const end time=date . now();

  console . log(` in the end `);输出时间,

  0时间,44

  1次,90

  2次,134

  最后你可以看到每次大概用了~45ms,代码主线程是顺序执行的。

  

异步 pbkdf2 方法,不跑在 main thread 里面

  从“操作系统”导入{ CPU };

  从“crypto”导入{ pbk df 2 };

  console . log(CPU()。长度);

  let start time=console . time( time-main-end );

  for(设索引=0;指数4;索引){

  start time=console . time(` time-$ { index } `);

  pbkdf2(secret ,` salt${index} `,100000,64, sha512 ,(err,derivedKey)={

  if(err)throw err;

  console . time end(` time-$ { index } `);

  });

  }

  console . time end( time-main-end );输出时间,

  时间-主要-结束:0.31毫秒

  时间-2分45秒646秒

  时间-0分46.055秒

  时间-3分46.846秒

  Time-1: 47.159ms这里主线程结束的比较早,但是,每次计算的时间是45ms,要知道一个cpu计算hash的时间是45ms,这里node肯定是用多线程进行hash计算的。

  如果我在这里把调用次数改为10,那么时间如下。可以看出,随着CPU核心数的用完,时间也在增加。再次证明node绝对使用多线程进行哈希计算。

  时间-主要-结束:0.451毫秒

  时间-1分44.977秒

  时间-2分46.069秒

  时间-3分50秒033秒

  时间-0分51秒381秒

  时间-5: 96.429ms //这里注意,从第五次开始就增加了

  时间-7分101.61秒

  时间-4分113.535秒

  时间-6分121.429秒

  时间-9分151.035秒

  时间-8: 152.585ms虽然这里证明了,node绝对启用了多线程。但是有个小问题?我电脑的CPU是AMD R5-5600U,6核12线程。但是为什么从第五次开始时间增加了呢?node没有充分利用我的CPU?

  原因是什么?

  节点使用预定义的线程池,其默认大小为4。

  让我们看一个例子,

  

HTTP request

  从“https”导入{ request };

  常量选项={

  主机名: www.baidu.com ,

  端口:443,

  路径:/img/PC _ 7 AC 6 a6 d 319 ba 4 AE 29 b 38 E5 e 4280 e 9122 . png ,

  方法:“GET”,

  };

  let start time=console . time(` main `);

  for(设索引=0;指数15;索引){

  start time=console . time(` time-$ { index } `);

  const req=request(options,(res)={

  console . log(` status code:$ { RES . status code } `);

  console . time end(` time-$ { index } `);

  res.on(data ,(d)={

  //process . stdout . write(d);

  });

  });

  req.on(错误,(错误)={

  console.error(错误);

  });

  req . end();

  }

  console . time end( main );主:13.927毫秒

  时间-2:83.247毫秒

  时间-4分89.641秒

  时间-3分91.497秒

  时间-12分91.661秒

  时间-5分94.677秒

  .

  时间-8分134.026秒

  时间-1分143.906秒

  时间-13:140.914毫秒

  Time-10: 144.088ms这里,主程序也提前结束了。在这里,我启动了15次http请求下载图片,他们花费的时间并没有成倍增长。似乎并没有受到线程池/cpu的影响。

  为什么?节点是否正在使用线程池?

  如果C的异步方法在Node后面,它会首先尝试是否有内核异步支持。比如这里,网络要用epoll (Linux)。如果内核不提供异步模式,节点将使用自己的线程池。

  因此,虽然http请求是异步的,但它是由内核实现的。内核完成后,会通知C,C会通知主线程处理回调。

  那么Node的哪些异步方法会使用线程池呢?哪些不会?

  本机内核异步

  TCP/UDP服务器客户端Unix域套接字(IPC)管道pipesdns.resolveXXXtty输入(stdin等)Unix信号子进程线程池

  Fs。*dns.lookuppipe (edge case)这也是大多数节点优化的起点。

  但是这些怎么和最重要的事件循环结合呢?

  

Event Loop

  相信大家对Event loop都很熟悉。事件循环就像一个分配器,

  如果遇到普通的javascript程序或者回调,就交给V8吧。

  如果同步方法后面是C写的,就交给C,在主线程上运行。

  如果异步方法后面是C写的,如果有内核异步支持,就从主线程交给内核。

  如果异步方法的后面是C写的,如果没有内核异步支持,就会从主线程交给线程池。

  如果线程池和内核有结果,它们会将结果返回给事件循环。如果注册了javascript回调,就交给V8处理。

  然后循环,直到没什么可处理的。

  所以 Node 不完全是单线程程序。

  更多关于node的信息,请访问:nodejs教程!就这样理解Node.js不是一个完整的单线程程序(分析)。更多详情请关注我们的其他相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: