ホームページ  >  記事  >  ウェブフロントエンド  >  Node.js + worker_threads がマルチスレッドを実装する方法について話しましょう。 (詳しい説明)

Node.js + worker_threads がマルチスレッドを実装する方法について話しましょう。 (詳しい説明)

青灯夜游
青灯夜游転載
2022-02-11 20:07:543920ブラウズ

この記事では、worker_threads モジュールを理解し、worker_threads を使用して Node でマルチスレッドを実装する方法を紹介し、worker_threads を使用して実際の例としてフィボナッチ数列を実行する方法を説明します。皆さんのお役に立ちますように。

Node.js + worker_threads がマルチスレッドを実装する方法について話しましょう。 (詳しい説明)

通常、Node.js はシングルスレッドとみなされます。メインスレッドはコーディングシーケンスに従ってプログラムコードを段階的に実行しますが、同期コードがブロックされるとメインスレッドが占有され、それ以降のプログラムコードの実行が停止します。そうです、Node.js のシングル スレッドは、メイン スレッドが「シングル スレッド」であることを指します。

単一スレッドによって引き起こされる問題を解決するために、この記事の主人公である worker_threads が登場します。 worker_threads は、Node.js v10.5.0 の実験的な機能として初めて登場しました。これを使用するには、コマンド ラインで --experimental-worker を指定する必要があります。 v12.11.0 安定バージョンまで正式に使用されません。

この記事では、worker_threadsの使い方と、worker_threadsを使ってフィボナッチ数列を実行する方法を実践例として紹介します。

前提条件

この記事を読んで利用するには、次のものが必要です:

  • インストール済みNode.js v12.11.0 以降のバージョン
  • #JavaScript 同期および非同期プログラミングの基本知識をマスターする
  • Node.js の動作原理をマスターする

worker_threads の概要

worker_threads このモジュールでは、JavaScript を並列実行するスレッドの使用が可能になります。

ワーカー スレッドは、CPU を集中的に使用する JavaScript 操作を実行する場合に役立ちます。これらは、I/O 集中型の作業にはあまり役に立ちません。 Node.js の組み込みの非同期 I/O 操作は、ワーカー スレッドよりも効率的です。

child_processcluster とは異なり、worker_threads はメモリを共有できます。これは、ArrayBuffer インスタンスを転送するか、SharedArrayBuffer インスタンスを共有することによって行われます。

worker_threads は、次の特性により、CPU パフォーマンスを最大限に活用するための最良のソリューションであることが証明されています。

  • これらは、単一の複数のスレッドで実行されます。プロセス。

  • 各スレッドはイベント ループを実行します。

  • JS エンジンのインスタンスをスレッドごとに 1 つ実行します。

  • 各スレッドは単一の Nodejs インスタンスを実行します。

worker_threads の仕組み

worker_threadsメインスレッド指定された スクリプトを実行することにより をファイルして作業します。各スレッドは他のスレッドから独立して実行されます。ただし、これらのスレッドはメッセージ チャネルを通じてメッセージをやり取りできます。

メイン スレッドUse worker.postMessage() 関数はメッセージ チャネルを使用し、Worker threadparentPort.postMessage() を使用します。 # ##関数。

公式サンプル コードを通じて理解を深めます:

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

if (isMainThread) {
  module.exports = function parseJSAsync(script) {
    return new Promise((resolve, reject) => {
      const worker = new Worker(__filename, {
        workerData: script
      });
      worker.on('message', resolve);
      worker.on('error', reject);
      worker.on('exit', (code) => {
        if (code !== 0)
          reject(new Error(`Worker stopped with exit code ${code}`));
      });
    });
  };
} else {
  const { parse } = require('some-js-parsing-library');
  const script = workerData;
  parentPort.postMessage(parse(script));
}

上記のコード

メイン スレッドWorker thread実行スクリプトと同じファイルを使用し(__filenameは現在の実行ファイルのパス)、isMainThreadを使用してメインスレッドと##を区別します。 #ワーカー スレッドランタイム ロジック。モジュールの外部公開メソッド parseJSAsync が呼び出されると、サブワーカー スレッドが生成され、parse 関数が実行されます。

Worker_threads 固有の使用法

このセクションでは、具体的な例を使用して、

worker_threads

Create ## の使用法を紹介します。 #ワーカー スレッド

スクリプト ファイル

workerExample.js:

const { workerData, parentPort } = require('worker_threads')
parentPort.postMessage({ welcome: workerData })
作成メイン スレッド

スクリプト ファイル

main.js:

const { Worker } = require('worker_threads')

const runWorker = (workerData) => {
    return new Promise((resolve, reject) => {
        // 引入 workerExample.js `工作线程`脚本文件
        const worker = new Worker('./workerExample.js', { workerData });
        worker.on('message', resolve);
        worker.on('error', reject);
        worker.on('exit', (code) => {
            if (code !== 0)
                reject(new Error(`stopped with  ${code} exit code`));
        })
    })
}

const main = async () => {
    const result = await runWorker('hello worker threads')
    console.log(result);
}

main().catch(err => console.error(err))
台湾のコマンド ライン実行の制御:
node main.js

出力:

{ welcome: 'hello worker threads' }

worker_threads フィボナッチ数列演算

このセクションでは、次のことを見てみましょう。 CPU 集中型の例では、フィボナッチ数列

を生成します。

このタスクがワーカー スレッドなしで完了した場合、nth

の期限が長くなるにつれてメイン スレッドがブロックされます。

作成ワーカー スレッド

スクリプト ファイル

worker.js

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

parentPort.postMessage(getFibonacciNumber(workerData.num))

function getFibonacciNumber(num) {
    if (num === 0) {
        return 0;
    }
    else if (num === 1) {
        return 1;
    }
    else {
        return getFibonacciNumber(num - 1) + getFibonacciNumber(num - 2);
    }
}
作成メイン スレッド

スクリプト ファイル

main.js :

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

let number = 30;

const worker = new Worker("./worker.js", {workerData: {num: number}});

worker.once("message", result => {
    console.log(`${number}th Fibonacci Result: ${result}`);
});

worker.on("error", error => {
    console.log(error);
});

worker.on("exit", exitCode => {
    console.log(`It exited with code ${exitCode}`);
})

console.log("Execution in main thread");
コンソール コマンド ライン実行:
node main.js

出力:

Execution in main thread
30th Fibonacci Result: 832040
It exited with code 0

main.js

ファイルで、クラスから開始します。前の例で見たように、インスタンスはワーカー スレッド

Worker を作成します。 結果を取得するために、3 つのイベントをリッスンします。

  • message响应工作线程发出消息。
  • exit工作线程停止执行的情况下触发的事件。
  • error发生错误时触发。

我们在最后一行main.js

console.log("Execution in main thread");

通过控制台的输出可得,主线程并没有被斐波那契数列运算执行而阻塞。

因此,只要在工作线程中处理 CPU 密集型任务,我们就可以继续处理其他任务而不必担心阻塞主线程。

结论

Node.js 在处理 CPU 密集型任务时一直因其性能而受到批评。通过有效地解决这些缺点,工作线程的引入提高了 Node.js 的功能。

有关worker_threads的更多信息,请在此处访问其官方文档。

思考

文章结束前留下思考,后续会在评论区做补充,欢迎一起讨论。

  • worker_threads线程空闲时候会被回收吗?
  • worker_threads共享内存如何使用?
  • 既然说到线程,那么应该有线程池?

更多node相关知识,请访问:nodejs 教程

以上がNode.js + worker_threads がマルチスレッドを実装する方法について話しましょう。 (詳しい説明)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。