加入收藏 | 设为首页 | 会员中心 | 我要投稿 核心网 (https://www.hxwgxz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 建站 > 正文

深入理解Node.js 进程与线程(8000字长文彻底搞懂)

发布时间:2019-08-20 03:46:39 所属栏目:建站 来源:koala
导读:前言 进程与线程是一个程序员的必知概念,面试经常被问及,但是一些文章内容只是讲讲理论知识,可能一些小伙伴并没有真的理解,在实际开发中应用也比较少。本篇文章除了介绍概念,通过Node.js 的角度讲解进程与线程,并且讲解一些在项目中的实战的应用,让

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

  1. const fs = require('fs') 
  2. setInterval(() => { 
  3.     console.log(new Date().getTime()) 
  4. }, 3000) 
  5.  
  6. fs.readFile('./index.html', () => {}) 

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

我们可以手动更改线程池默认大小:

  1. process.env.UV_THREADPOOL_SIZE = 64 

一行代码轻松把线程变成 71。

Libuv

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

libuv架构图

深入理解Node.js 进程与线程(8000字长文彻底搞懂)

在Window环境下,libuv直接使用Windows的IOCP来实现异步IO。在非Windows环境下,libuv使用多线程来模拟异步IO。

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

Node.js 线程创建

直到 Node 10.5.0 的发布,官方才给出了一个实验性质的模块 worker_threads 给 Node 提供真正的多线程能力。

先看下简单的 demo:

  1. const { 
  2.   isMainThread, 
  3.   parentPort, 
  4.   workerData, 
  5.   threadId, 
  6.   MessageChannel, 
  7.   MessagePort, 
  8.   Worker 
  9. } = require('worker_threads'); 
  10.  
  11. function mainThread() { 
  12.   for (let i = 0; i < 5; i++) { 
  13.     const worker = new Worker(__filename, { workerData: i }); 
  14.     worker.on('exit', code => { console.log(`main: worker stopped with exit code ${code}`); }); 
  15.     worker.on('message', msg => { 
  16.       console.log(`main: receive ${msg}`); 
  17.       worker.postMessage(msg + 1); 
  18.     }); 
  19.   } 
  20.  
  21. function workerThread() { 
  22.   console.log(`worker: workerDate ${workerData}`); 
  23.   parentPort.on('message', msg => { 
  24.     console.log(`worker: receive ${msg}`); 
  25.   }), 
  26.   parentPort.postMessage(workerData); 
  27.  
  28. if (isMainThread) { 
  29.   mainThread(); 
  30. } else { 
  31.   workerThread(); 

上述代码在主线程中开启五个子线程,并且主线程向子线程发送简单的消息。

由于 worker_thread 目前仍然处于实验阶段,所以启动时需要增加 --experimental-worker flag,运行后观察活动监视器,开启了5个子线程

深入理解Node.js 进程与线程(8000字长文彻底搞懂)

worker_thread 模块

worker_thread 核心代码(地址https://github.com/nodejs/nod...)

(编辑:核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读