NodeJs Worker threads

 后端   小卒子   2024-09-11 09:29   214
  nodejs

Node.js 的 worker_threads 模块提供了在 Node.js 环境中创建和管理线程的能力。这使得可以在多个线程中并行执行 JavaScript 代码,从而提高应用程序的性能,尤其是对于 CPU 密集型任务。该模块是 Node.js 内置的,提供了一个与浏览器 Web Workers 类似的 API。

模块引入

在 Node.js 中,你可以通过 worker_threads 模块来使用线程功能:

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

或者使用 ES 模块语法:

import { Worker, isMainThread, parentPort, workerData } from 'worker_threads';

主要类和接口

Node.js worker_threads 模块主要包括以下几个类和接口:

  1. Worker
  2. isMainThread
  3. parentPort
  4. workerData
  5. MessagePort

1. Worker

Worker 类用于创建新的线程并在其中运行 JavaScript 代码。每个 Worker 实例代表一个独立的线程。

创建 Worker 示例:

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

// 创建一个新的 Worker 实例
const worker = new Worker('./worker.js', {
  workerData: { foo: 'bar' }
});

// 监听 Worker 发送的消息
worker.on('message', (message) => {
  console.log('Received message from worker:', message);
});

// 监听 Worker 错误
worker.on('error', (error) => {
  console.error('Error from worker:', error);
});

// 监听 Worker 退出
worker.on('exit', (code) => {
  if (code !== 0) {
    console.error(`Worker stopped with exit code ${code}`);
  }
});

构造函数:

  • new Worker(filename[, options])

    • filename {string} 运行 Worker 的 JavaScript 文件路径。
    • options {Object} 配置选项。支持以下选项:
      • workerData {any} 传递给 Worker 线程的数据。
      • stdout {boolean} 默认为 true。如果为 false,则不在控制台输出 Worker 的 stdout
      • stderr {boolean} 默认为 true。如果为 false,则不在控制台输出 Worker 的 stderr
      • execArgv {string[]} 启动 Worker 时传递给 Node.js 的额外参数。

实例方法:

  • postMessage(value[, transferList]): 向 Worker 发送消息。value 是要发送的消息,transferList 是一个可选的 Array,指定要转移的 ArrayBufferMessagePort 对象。
  • terminate(): 终止 Worker 线程并清理资源。返回一个 Promise,在 Worker 线程被终止时解析。

2. isMainThread

isMainThread 是一个布尔值,表示当前代码是否在主线程中。主线程是创建 Worker 实例的线程。

示例:

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

if (isMainThread) {
  console.log('This is the main thread');
} else {
  console.log('This is a worker thread');
}

3. parentPort

parentPort 是一个 MessagePort 对象,用于在 Worker 线程和主线程之间进行消息传递。它只能在 Worker 线程中访问。

示例:

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

parentPort.postMessage('Hello from Worker');

4. workerData

workerData 是一个对象,包含传递给 Worker 线程的数据。在 Worker 线程中可以通过 worker_threads.workerData 访问这些数据。

示例:

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

console.log('Worker data:', workerData);

5. MessagePort

MessagePort 对象用于在不同线程之间传递消息。它提供了以下方法和事件:

方法:

  • postMessage(value[, transferList]): 向对端发送消息。value 是要发送的消息,transferList 是一个可选的 Array,指定要转移的 ArrayBufferMessagePort 对象。

事件:

  • message: 当接收到消息时触发。事件处理程序接收到一个 MessageEvent 对象,其中包含接收到的消息。

示例:完整的 Worker 使用示例

worker.js

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

// 处理传入的消息
parentPort.on('message', (message) => {
  console.log('Received message from main thread:', message);

  // 使用 workerData
  console.log('Worker data:', workerData);

  // 发送消息到主线程
  parentPort.postMessage('Hello from worker');
});

main.js

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

// 创建一个新的 Worker 实例
const worker = new Worker('./worker.js', {
  workerData: { foo: 'bar' }
});

// 监听 Worker 发送的消息
worker.on('message', (message) => {
  console.log('Received message from worker:', message);
});

// 发送消息到 Worker
worker.postMessage('Hello from main thread');

// 处理 Worker 错误
worker.on('error', (error) => {
  console.error('Error from worker:', error);
});

// 处理 Worker 退出
worker.on('exit', (code) => {
  if (code !== 0) {
    console.error(`Worker stopped with exit code ${code}`);
  }
});

总结

Node.js 的 worker_threads 模块提供了强大的多线程功能,使得开发者可以在 Node.js 环境中并行执行 JavaScript 代码。通过 Worker 类、isMainThread 属性、parentPort 对象、workerDataMessagePort 对象,可以高效地创建和管理线程,实现并行处理,提升应用程序性能。这个模块为 CPU 密集型任务提供了有效的解决方案,适用于需要高性能计算的场景。