多くの人は、シングルスレッドの NodeJS がマルチスレッド バックエンドとどのように競合できるのかを理解していないようです。
その理由を知るには、Nodejs がシングルスレッドであることが実際に何を意味するのかを理解する必要があります。
JavaScript 自体は元々、フォームの検証や応答の作成などの単純な処理を行うために作成されました。Node.js の作成者 Ryan Dahl が JavaScript を使用してサーバーサイド コードを記述できるようにしたのは 2009 年になってからです。
マルチスレッドをサポートするサーバーサイド言語には、スレッド間や他のスレッド指向の機能を同期するためのさまざまな構造と構造があります。
これらをサポートするには、JavaScript が言語全体を変更する必要があることを意味しますが、これは JavaScript の作成者の考えに反します。したがって、純粋な JavaScript でマルチスレッドをサポートするために、Dahl は回避策を作成する必要がありました。見てみましょう!
Node.jsはどのように機能するのでしょうか?
Node.js は 2 種類のスレッドを使用します。1 つはイベント ループによって処理されるメイン スレッド、もう 1 つはワーカー スレッドのプール内のいくつかのセカンダリ スレッドです。
イベント ループNode.js のノンブロッキング I/O 操作を処理するメカニズムは、JavaScript がシングルスレッドであっても、可能な場合には操作をシステム カーネルにオフロードします。 JavaScript 操作がスレッドをブロックすると、イベント ループもブロックされます。
ワーカー プールは、個別のスレッドを生成して処理し、タスクを同期的に実行して結果をイベント ループに返す実行モデルです。次に、イベント ループはその結果を使用して、提供されたコールバックを実行します。
基本的に、ワーカー プールは非同期 I/O 操作 (主にシステム ディスクおよびネットワークとの対話) を処理します。 fs (I/O 負荷が高い) や crypto (CPU 負荷が高い) など、一部のモジュールは、すぐに使用できるワーカー プールを使用します。ワーカー プールは libuv で実装されており、ノードが JavaScript と C++ の間で内部的にデータを転送する必要がある場合に、わずかではありますがほとんど無視できるほどの遅延が発生します。
イベント ループとワーク プールの意味を理解した後、次のコードを見てみましょう。
上記のコードでは、イベントを同期的に待つ必要はありません。ファイルを読み取るタスクをワーカー プールに委任し、結果を使用して提供された関数を呼び出します。ワーカー プールには独自のスレッドがあるため、ファイルの読み取り中もイベント ループは通常どおり実行を続けることができます。
紹介しましょう: worker_threads
Node.js 10.5.0 のリリースにより、worker_threads が登場しました。 JavaScript での単純なマルチスレッド アプリケーションの作成をサポートします。
worker_threads は、nodejs モジュール パッケージです。スレッド ワーカーは、別のスレッドで生成されるコードの一部 (通常はファイルから取得されます) です。
スレッド ワーカー、ワーカー、スレッドという用語は、多くの場合同じ意味で使用されることに注意することが重要です。それらはすべて同じものを指します。
Node.js のワーカー スレッドは、負荷の高い JavaScript タスクを実行するのに役立ちます。スレッドの助けを借りて、ワーカーは JavaScript コードを簡単に並列実行できるため、より高速かつ効率的になります。メインスレッドを妨げることなく、重いタスクを完了できます。
ワーカー スレッドは、Node.js の古いバージョンでは導入されませんでした。したがって、開始するにはまず Node.js を更新します。
次に、スレッドを実装するための 2 つのファイルを次のように作成します。
ファイル名:worker.js
const {workerData,parentPort} = require('worker_threads'); console.log(`${workerData} が偉い人たちとどのようにくつろぎたいかについて書きます`); parentPort.postMessage({ ファイル名: workerData, ステータス: '完了' });
ファイル名:index.js
const { Worker } = require('worker_threads'); const runSerice = (workerData) => { return new Promise((解決、拒否) => { const worker = new Worker('./worker.js', {workerData }); worker.on('メッセージ', 解決); worker.on('エラー'、拒否); worker.on('exit', (コード) => { if (コード !== 0) 拒否(新しいエラー(`ワーカー スレッドは終了コード ${code}` で停止しました)); }); }); }; const run = async () => { const result = await runSerice('Tunde Ednut'); console.log(結果); }; run().catch((err) => console.error(err));
出力: