使用 Node.js 多线程进行并行处理

很多人似乎都无法理解单线程 NodeJS 是如何与多线程后端竞争的。

要找出原因,我们必须了解 Node.js 是单线程的真正含义。

JavaScript 本身最初是为了做一些简单的事情而创建的,比如验证表单、做出响应等,直到 2009 年,Node.js 的创建者 Ryan Dahl 才使使用 JavaScript 编写服务器端代码成为可能。

支持多线程的服务器端语言具有各种结构和构造,用于在线程和其他面向线程的特性之间同步。

支持这些东西意味着 JavaScript 需要改变整个语言,而这也违背了javascript缔造者的想法。因此,为了让纯 JavaScript 支持多线程,Dahl 必须创建一种解决方法。让我们来看看吧!


Node.js 是如何工作的?

Node.js 使用两种线程:由事件循环处理的主线程和工作线程池的几个辅助线程。

事件循环Node.js 处理非阻塞 I/O 操作的机制——尽管 JavaScript 是单线程处理的——当有可能的时候,它们会把操作转移到系统内核中去。当 JavaScript 操作阻塞线程时,事件循环也被阻塞。

工作池是一种执行模型,它产生和处理单独的线程,然后同步执行任务并将结果返回给事件循环。然后事件循环使用所述结果执行提供的回调。

基本上,工作池处理异步 I/O 操作——主要是与系统磁盘和网络的交互。一些模块使用开箱即用的工作池,例如 fs(I/O-heavy)或 crypto(CPU-heavy)。工作池是在 libuv 中实现的,当 Node 需要在 JavaScript 和 C++ 之间内部传输数据时,这会导致轻微的延迟,但几乎可以忽略。

理解了事件循环和工作池的含义之后 我们看下下面代码:

fs 是一个 nodejs 模块

在上面的代码中,我们不必同步等待事件。我们将读取文件的任务委托给工作池,并使用结果调用提供的函数。由于工作池有自己的线程,因此事件循环可以在读取文件的同时继续正常执行。


给大家介绍一下:worker_threads

随着 Node.js 10.5.0 的发布,出现了 worker_threads。它支持在 JavaScript 中创建简单的多线程应用程序

worker_threads 是一个nodejs模块包。线程工作者是在单独线程中生成的一段代码(通常从文件中取出)。

需要注意的是,术语线程工作者、工作者和线程通常可以互换使用。它们都指的是同一件事。

image.png Node.js 中的工作线程对于执行繁重的 JavaScript 任务很有用。在线程的帮助下,Worker 可以轻松地并行运行 JavaScript 代码,从而使其更快、更高效。我们可以在不干扰主线程的情况下完成繁重的任务。

旧版本的 Node.js 中没有引入工作线程。因此,首先更新您的 Node.js 以开始使用。

现在创建两个文件来实现线程,如下所示:

文件名:worker.js


const { workerData, parentPort } = require('worker_threads');

console.log(`Write-up on how ${workerData} wants to chill with the big boys`);

parentPort.postMessage({ filename: workerData, status: 'Done' });

复制代码

文件名:index.js

const { Worker } = require('worker_threads');

const runSerice = (workerData) => {
  return new Promise((resolve, reject) => {
    const worker = new Worker('./worker.js', { workerData });
    worker.on('message', resolve);
    worker.on('error', reject);
    worker.on('exit', (code) => {
      if (code !== 0)
        reject(new Error(`Worker Thread stopped with exit code ${code}`));
    });
  });
};
const run = async () => {
  const result = await runSerice('Tunde Ednut');
  console.log(result);
};

run().catch((err) => console.error(err));

复制代码

输出:

image.png

本文正在参与技术专题征文Node.js进阶之路,点击查看详情

猜你喜欢

转载自juejin.im/post/7075256441019465742