欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

Nodejs中多線(xiàn)程的操作方法

這篇文章主要介紹“Nodejs中多線(xiàn)程的操作方法”,在日常操作中,相信很多人在Nodejs中多線(xiàn)程的操作方法問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”Nodejs中多線(xiàn)程的操作方法”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

站在用戶(hù)的角度思考問(wèn)題,與客戶(hù)深入溝通,找到大田網(wǎng)站設(shè)計(jì)與大田網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶(hù)體驗(yàn)好的作品,建站類(lèi)型包括:成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、外貿(mào)網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、主機(jī)域名、網(wǎng)頁(yè)空間、企業(yè)郵箱。業(yè)務(wù)覆蓋大田地區(qū)。

本文測(cè)試使用環(huán)境:
系統(tǒng):macOS Mojave 10.14.2
CPU:4 核 2.3 GHz
Node: 10.15.1

從 Node 線(xiàn)程說(shuō)起

一般人理解 Node 是單線(xiàn)程的,所以 Node 啟動(dòng)后線(xiàn)程數(shù)應(yīng)該為 1,我們做實(shí)驗(yàn)看一下。【推薦學(xué)習(xí):《nodejs 教程》】

setInterval(() => {
  console.log(new Date().getTime())
}, 3000)

Nodejs中多線(xiàn)程的操作方法

可以看到 Node 進(jìn)程占用了 7 個(gè)線(xiàn)程。為什么會(huì)有 7 個(gè)線(xiàn)程呢?

我們都知道,Node 中最核心的是 v8 引擎,在 Node 啟動(dòng)后,會(huì)創(chuàng)建 v8 的實(shí)例,這個(gè)實(shí)例是多線(xiàn)程的。

  • 主線(xiàn)程:編譯、執(zhí)行代碼。

  • 編譯/優(yōu)化線(xiàn)程:在主線(xiàn)程執(zhí)行的時(shí)候,可以?xún)?yōu)化代碼。

  • 分析器線(xiàn)程:記錄分析代碼運(yùn)行時(shí)間,為 Crankshaft 優(yōu)化代碼執(zhí)行提供依據(jù)。

  • 垃圾回收的幾個(gè)線(xiàn)程。

所以大家常說(shuō)的 Node 是單線(xiàn)程的指的是 JavaScript 的執(zhí)行是單線(xiàn)程的,但 Javascript 的宿主環(huán)境,無(wú)論是 Node 還是瀏覽器都是多線(xiàn)程的。

Node 有兩個(gè)編譯器:
full-codegen:簡(jiǎn)單快速地將 js 編譯成簡(jiǎn)單但是很慢的機(jī)械碼。
Crankshaft:比較復(fù)雜的實(shí)時(shí)優(yōu)化編譯器,編譯高性能的可執(zhí)行代碼。

某些異步 IO 會(huì)占用額外的線(xiàn)程

還是上面那個(gè)例子,我們?cè)诙〞r(shí)器執(zhí)行的同時(shí),去讀一個(gè)文件:

const fs = require('fs')

setInterval(() => {
    console.log(new Date().getTime())
}, 3000)

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

Nodejs中多線(xiàn)程的操作方法

線(xiàn)程數(shù)量變成了 11 個(gè),這是因?yàn)樵?Node 中有一些 IO 操作(DNS,F(xiàn)S)和一些 CPU 密集計(jì)算(Zlib,Crypto)會(huì)啟用 Node 的線(xiàn)程池,而線(xiàn)程池默認(rèn)大小為 4,因?yàn)榫€(xiàn)程數(shù)變成了 11。

我們可以手動(dòng)更改線(xiàn)程池默認(rèn)大小:

process.env.UV_THREADPOOL_SIZE = 64

一行代碼輕松把線(xiàn)程變成 71。

Nodejs中多線(xiàn)程的操作方法

cluster 是多線(xiàn)程嗎?

Node 的單線(xiàn)程也帶來(lái)了一些問(wèn)題,比如對(duì) cpu 利用不足,某個(gè)未捕獲的異常可能會(huì)導(dǎo)致整個(gè)程序的退出等等。因?yàn)?Node 中提供了 cluster 模塊,cluster 實(shí)現(xiàn)了對(duì) child_process 的封裝,通過(guò) fork 方法創(chuàng)建子進(jìn)程的方式實(shí)現(xiàn)了多進(jìn)程模型。比如我們最常用到的 pm2 就是其中最優(yōu)秀的代表。

我們看一個(gè) cluster 的 demo:

const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  console.log(`主進(jìn)程 ${process.pid} 正在運(yùn)行`);
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`工作進(jìn)程 ${worker.process.pid} 已退出`);
  });
} else {
  // 工作進(jìn)程可以共享任何 TCP 連接。
  // 在本例子中,共享的是 HTTP 服務(wù)器。
  http.createServer((req, res) => {
    res.writeHead(200);
    res.end('Hello World');
  }).listen(8000);
  console.log(`工作進(jìn)程 ${process.pid} 已啟動(dòng)`);
}

這個(gè)時(shí)候看下活動(dòng)監(jiān)視器:

Nodejs中多線(xiàn)程的操作方法

一共有 9 個(gè)進(jìn)程,其中一個(gè)主進(jìn)程,cpu 個(gè)數(shù) x cpu 核數(shù) = 2 x 4 = 8 個(gè) 子進(jìn)程。

所以無(wú)論 child_process 還是 cluster,都不是多線(xiàn)程模型,而是多進(jìn)程模型。雖然開(kāi)發(fā)者意識(shí)到了單線(xiàn)程模型的問(wèn)題,但是沒(méi)有從根本上解決問(wèn)題,而且提供了一個(gè)多進(jìn)程的方式來(lái)模擬多線(xiàn)程。從前面的實(shí)驗(yàn)可以看出,雖然 Node (V8)本身是具有多線(xiàn)程的能力的,但是開(kāi)發(fā)者并不能很好的利用這個(gè)能力,更多的是由 Node 底層提供的一些方式來(lái)使用多線(xiàn)程。Node 官方說(shuō):

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.

但是對(duì)于 JavaScript 開(kāi)發(fā)者,一直沒(méi)有一個(gè)標(biāo)準(zhǔn)的、好用的方式來(lái)使用 Node 的多線(xiàn)程能力。

真 - Node 多線(xiàn)程

直到 Node 10.5.0 的發(fā)布,官方才給出了一個(gè)實(shí)驗(yàn)性質(zhì)的模塊 worker_threads 給 Node 提供真正的多線(xiàn)程能力。

先看下簡(jiǎn)單的 demo:

const {
  isMainThread,
  parentPort,
  workerData,
  threadId,
  MessageChannel,
  MessagePort,
  Worker
} = require('worker_threads');

function mainThread() {
  for (let i = 0; i < 5; i++) {
    const worker = new Worker(__filename, { workerData: i });
    worker.on('exit', code => { console.log(`main: worker stopped with exit code ${code}`); });
    worker.on('message', msg => {
      console.log(`main: receive ${msg}`);
      worker.postMessage(msg + 1);
    });
  }
}

function workerThread() {
  console.log(`worker: workerDate ${workerData}`);
  parentPort.on('message', msg => {
    console.log(`worker: receive ${msg}`);
  }),
  parentPort.postMessage(workerData);
}

if (isMainThread) {
  mainThread();
} else {
  workerThread();
}

上述代碼在主線(xiàn)程中開(kāi)啟五個(gè)子線(xiàn)程,并且主線(xiàn)程向子線(xiàn)程發(fā)送簡(jiǎn)單的消息。

由于 worker_thread 目前仍然處于實(shí)驗(yàn)階段,所以啟動(dòng)時(shí)需要增加 --experimental-worker flag,運(yùn)行后觀察活動(dòng)監(jiān)視器:

Nodejs中多線(xiàn)程的操作方法

不多不少,正好多了五個(gè)子線(xiàn)程。

worker_thread 模塊

worker_thread 核心代碼

worker_thread 模塊中有 4 個(gè)對(duì)象和 2 個(gè)類(lèi)。

  • isMainThread: 是否是主線(xiàn)程,源碼中是通過(guò) threadId === 0 進(jìn)行判斷的。

  • MessagePort: 用于線(xiàn)程之間的通信,繼承自 EventEmitter。

  • MessageChannel: 用于創(chuàng)建異步、雙向通信的通道實(shí)例。

  • threadId: 線(xiàn)程 ID。

  • Worker: 用于在主線(xiàn)程中創(chuàng)建子線(xiàn)程。第一個(gè)參數(shù)為 filename,表示子線(xiàn)程執(zhí)行的入口。

  • parentPort: 在 worker 線(xiàn)程里是表示父進(jìn)程的 MessagePort 類(lèi)型的對(duì)象,在主線(xiàn)程里為 null

  • workerData: 用于在主進(jìn)程中向子進(jìn)程傳遞數(shù)據(jù)(data 副本)

來(lái)看一個(gè)進(jìn)程通信的例子:

const assert = require('assert');
const {
  Worker,
  MessageChannel,
  MessagePort,
  isMainThread,
  parentPort
} = require('worker_threads');
if (isMainThread) {
  const worker = new Worker(__filename);
  const subChannel = new MessageChannel();
  worker.postMessage({ hereIsYourPort: subChannel.port1 }, [subChannel.port1]);
  subChannel.port2.on('message', (value) => {
    console.log('received:', value);
  });
} else {
  parentPort.once('message', (value) => {
    assert(value.hereIsYourPort instanceof MessagePort);
    value.hereIsYourPort.postMessage('the worker is sending this');
    value.hereIsYourPort.close();
  });
}

更多詳細(xì)用法可以查看官方文檔。

多進(jìn)程 vs 多線(xiàn)程

根據(jù)大學(xué)課本上的說(shuō)法:“進(jìn)程是資源分配的最小單位,線(xiàn)程是CPU調(diào)度的最小單位”,這句話(huà)應(yīng)付考試就夠了,但是在實(shí)際工作中,我們還是要根據(jù)需求合理選擇。

下面對(duì)比一下多線(xiàn)程與多進(jìn)程:

屬性多進(jìn)程多線(xiàn)程比較
數(shù)據(jù)數(shù)據(jù)共享復(fù)雜,需要用IPC;數(shù)據(jù)是分開(kāi)的,同步簡(jiǎn)單因?yàn)楣蚕磉M(jìn)程數(shù)據(jù),數(shù)據(jù)共享簡(jiǎn)單,同步復(fù)雜各有千秋
CPU、內(nèi)存占用內(nèi)存多,切換復(fù)雜,CPU利用率低占用內(nèi)存少,切換簡(jiǎn)單,CPU利用率高多線(xiàn)程更好
銷(xiāo)毀、切換創(chuàng)建銷(xiāo)毀、切換復(fù)雜,速度慢創(chuàng)建銷(xiāo)毀、切換簡(jiǎn)單,速度很快多線(xiàn)程更好
coding編碼簡(jiǎn)單、調(diào)試方便編碼、調(diào)試復(fù)雜多進(jìn)程更好
可靠性進(jìn)程獨(dú)立運(yùn)行,不會(huì)相互影響線(xiàn)程同呼吸共命運(yùn)多進(jìn)程更好
分布式可用于多機(jī)多核分布式,易于擴(kuò)展只能用于多核分布式多進(jìn)程更好

上述比較僅表示一般情況,并不絕對(duì)。

work_thread 讓 Node 有了真正的多線(xiàn)程能力,算是不小的進(jìn)步。

到此,關(guān)于“Nodejs中多線(xiàn)程的操作方法”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!

網(wǎng)站題目:Nodejs中多線(xiàn)程的操作方法
URL標(biāo)題:http://www.chinadenli.net/article44/geepee.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供靜態(tài)網(wǎng)站網(wǎng)站建設(shè)用戶(hù)體驗(yàn)網(wǎng)站導(dǎo)航網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都做網(wǎng)站