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

Node.js多线程完全指南

发布时间:2019-03-29 21:23:45 所属栏目:建站 来源:疯狂的技术宅
导读:许多人都想知道单线程的 Node.js 怎么能与多线程后端竞争。思量到其所谓的单线程特征,很多大公司选择 Node 作为厥后端好像违背直觉。要想知道缘故起因,必需领略其单线程的真正寄义。 JavaScript 的计划很是得当在网上做较量简朴的工作,好比验证表单,可能说
副问题[/!--empirenews.page--]

Node.js多线程完全指南

许多人都想知道单线程的 Node.js 怎么能与多线程后端竞争。思量到其所谓的单线程特征,很多大公司选择 Node 作为厥后端好像违背直觉。要想知道缘故起因,必需领略其单线程的真正寄义。

JavaScript 的计划很是得当在网上做较量简朴的工作,好比验证表单,可能说建设彩虹色的鼠标轨迹。 在2009年,Node.js的首创人 Ryan Dahl使开拓职员可以用该说话编写后端代码。

凡是支持多线程的后端说话具有各类机制,用于在线程和其他面向线程的成果之间同步数据。要向 JavaScript 添加对此类成果的支持,必要修改整个说话,这不是 Dahl 的方针。为了让纯 JavaScript 支持多线程,他必需想一个变通要领。接下来让我们试探一下个中的机密……

Node.js 是怎样事变的

Node.js 行使两种线程:event loop 处理赏罚的主线程和 worker pool 中的几个帮助线程。

变乱轮回是一种机制,它回收回调(函数)并注册它们,筹备在未来的某个时候执行。它与相干的 JavaScript 代码在统一个线程中运行。当 JavaScript 操纵阻塞线程时,变乱轮回也会被阻止。

事变池是一种执行模子,它发生并处理赏罚单独的线程,然后同步执利用命,并将功效返回到变乱轮回。变乱轮回行使返回的功效执行提供的回调。

简而言之,它认真异步 I/O操纵 —— 首要是与体系磁盘和收集的交互。它首要由诸如 fs(I/O 麋集)或 crypto(CPU 麋集)等模块行使。事变池用 libuv 实现,当 Node 必要在 JavaScript 和 C++ 之间举办内部通讯时,会导致稍微的耽误,但这险些不行察觉。

基于这两种机制,我们可以编写如下代码:

  1. fs.readFile(path.join(__dirname, './package.json'), (err, content) => {  
  2.  if (err) {  
  3.    return null;  
  4.  }  
  5.  console.log(content.toString());  
  6. }); 

前面提到的 fs 模块汇报事变池行使个中一个线程来读取文件的内容,并在完成后关照变乱轮回。然后变乱轮回获取提供的回调函数,并用文件的内容执行它。

以上长短阻塞代码的示例,我们不必同步守候某事的产生。只需汇报事变池去读取文件,并勤奋效去挪用提供的函数即可。因为事变池有本身的线程,因此变乱轮回可以在读取文件时继承正常执行。

在不必要同步执行某些伟大操纵时,这统统都息事宁人:任何运行时刻太长的函数城市阻塞线程。假如应用措施中有大量这类成果,就也许会明明低落处事器的吞吐量,乃至完全冻结它。在这种环境下,无法继承将事变委派给事变池。

在必要对数据举办伟大的计较时(如AI、呆板进修或大数据)无法真正有用地行使 Node.js,由于操纵阻塞了主(且独一)线程,使处事器无相应。在 Node.js v10.5.0 宣布之前就是这种环境,在这一版本增进了对多线程的支持。

简介:worker_threads

worker_threads 模块应承我们建设成果一切的多线程 Node.js 措施。

thread worker 是在单独的线程中天生的一段代码(凡是从文件中取出)。

留意,术语 thread worker,worker 和 thread 常常交流行使,他们都指的是统一件事。

要想行使 thread worker,必需导入 worker_threads 模块。让我们先写一个函数来辅佐我们天生这些thread worker,然后再接头它们的属性。

  1. type WorkerCallback = (err: any, result?: any) => any;  
  2. export function runWorker(path: string, cb: WorkerCallback, workerData: object | nullnull = null) {  
  3.  const worker = new Worker(path, { workerData });  
  4.  worker.on('message', cb.bind(null, null));  
  5.  worker.on('error', cb);  
  6.  worker.on('exit', (exitCode) => {  
  7.    if (exitCode === 0) {  
  8.      return null;  
  9.    }  
  10.    return cb(new Error(`Worker has stopped with code ${exitCode}`));  
  11.  });  
  12.  return worker;  

要建设一个 worker,起首必需建设一个 Worker 类的实例。它的第一个参数提供了包括 worker 的代码的文件的路径;第二个参数提供了一个名为 workerData 的包括一个属性的工具。这是我们但愿线程在开始运行时可以会见的数据。

请留意:不管你是用的是 JavaScript, 照旧最终要转换为 JavaScript 的说话(譬喻,TypeScript),路径应该始终引用带有 .js 或 .mjs 扩展名的文件。

我还想指出为什么行使回调要领,而不是返回在触发 message 变乱时将办理的 promise。这是由于 worker 可以发送很多 message 变乱,而不是一个。

正如你在上面的例子中所看到的,线程间的通讯是基于变乱的,这意味着我们配置了 worker 在发送给定变乱后挪用的侦听器。

以下是最常见的变乱:

  1. worker.on('error', (error) => {}); 

(编辑:河北网)

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

热点阅读