Worker Threads

Node.js で CPU 集約的な処理をメインスレッドをブロックせずに別スレッドで実行する仕組み

Node.js並行処理

Worker Threads とは

Worker Threads は、Node.jsCPU 集約的な処理をメインスレッドとは別のスレッドで実行する仕組みである。Node.js 10.5 で実験的に導入され、12 LTS で安定版になった。

Node.js はシングルスレッドのイベントループで I/O を効率的に処理するが、CPU を長時間占有する処理 (画像処理、暗号化、大量データの変換) はイベントループをブロックし、他のリクエストが処理できなくなる。Worker Threads はこの問題を解決する。

基本的な使い方

基本的な使い方のコード例を示す。

// main.ts (メインスレッド)
import { Worker } from 'worker_threads';

function runWorker(data: number[]): Promise<number> {
  return new Promise((resolve, reject) => {
    const worker = new Worker('./worker.ts', { workerData: data });
    worker.on('message', resolve);
    worker.on('error', reject);
  });
}

// メインスレッドはブロックされない
const result = await runWorker([1, 2, 3, 4, 5]);
console.log('Sum:', result);

// worker.ts (ワーカースレッド)
import { parentPort, workerData } from 'worker_threads';

// CPU 集約的な処理
const sum = (workerData as number[]).reduce((a, b) => a + b, 0);
parentPort!.postMessage(sum);

イベントループとの関係

イベントループとの関係を図で示す。

メインスレッド (イベントループ)
├── HTTP リクエストの受信・レスポンス送信
├── I/O 操作のコールバック処理
└── Worker Thread への処理委譲

Worker Thread 1: 画像リサイズ処理
Worker Thread 2: PDF 生成処理
Worker Thread 3: データ変換処理

メインスレッドは I/O とリクエストのルーティングに専念し、CPU 集約的な処理は Worker Thread に委譲する。

Worker Threads vs Child Process

Worker Threads と Child Process の違いを以下にまとめる。

観点Worker ThreadsChild Process (fork)
メモリ共有可能 (SharedArrayBuffer)独立 (プロセス間通信が必要)
起動コスト低い (スレッド生成)高い (プロセス生成)
分離レベル同一プロセス内完全に独立
適するケースCPU 集約的な計算外部コマンドの実行、クラッシュ分離

使うべきケースと使うべきでないケース

使うべきケースと使うべきでないケースを以下に示す。

使うべき使うべきでない
画像・動画の処理DB クエリ (I/O は非同期で十分)
暗号化・ハッシュ計算HTTP リクエスト (I/O)
大量データの変換・集計ファイル読み書き (I/O)
PDF 生成単純な CRUD 処理

I/O バウンドな処理には Worker Threads は不要だ。Node.js の非同期 I/O で十分に効率的に処理できる。

より深く学ぶには関連書籍が役立つ。

この記事は役に立ちましたか?

関連用語

関連する記事