worker_threads 工作线程
node:worker_threads
模块允许使用并行执行 JavaScript 的线程。
要访问它:
const worker = require('node:worker_threads');
工作线程对于执行 CPU 密集型的 JavaScript 操作很有用。 它们对 I/O 密集型的工作帮助不大。 Node.js 内置的异步 I/O 操作比工作线程更高效。
与 child_process
或 cluster
不同,worker_threads
可以共享内存。
它们通过传输 ArrayBuffer
实例或共享 SharedArrayBuffer
实例来实现。
const {
Worker, isMainThread, parentPort, workerData
} = require('node: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));
}
上面的示例为每个 parseJSAsync()
调用衍生工作线程。
在实践中,为这些类型的任务使用工作线程池。
否则,创建工作线程的开销可能会超过其收益。
当实现工作线程池时,使用 AsyncResource
API 通知诊断工具(例如提供异步的堆栈跟踪)有关任务与其结果之间的相关性。
有关示例实现,请参阅 async_hooks
文档中的“将 AsyncResource
用于 Worker
线程池”
默认情况下,工作线程继承非进程特定的选项。
参考 Worker
构造函数选项 了解如何自定义工作线程选项,特别是 argv
和 execArgv
选项。
Source Code: lib/worker_threads.js
The node:worker_threads
module enables the use of threads that execute
JavaScript in parallel. To access it:
const worker = require('node:worker_threads');
Workers (threads) are useful for performing CPU-intensive JavaScript operations. They do not help much with I/O-intensive work. The Node.js built-in asynchronous I/O operations are more efficient than Workers can be.
Unlike child_process
or cluster
, worker_threads
can share memory. They do
so by transferring ArrayBuffer
instances or sharing SharedArrayBuffer
instances.
const {
Worker, isMainThread, parentPort, workerData
} = require('node: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));
}
The above example spawns a Worker thread for each parseJSAsync()
call. In
practice, use a pool of Workers for these kinds of tasks. Otherwise, the
overhead of creating Workers would likely exceed their benefit.
When implementing a worker pool, use the AsyncResource
API to inform
diagnostic tools (e.g. to provide asynchronous stack traces) about the
correlation between tasks and their outcomes. See
"Using AsyncResource
for a Worker
thread pool"
in the async_hooks
documentation for an example implementation.
Worker threads inherit non-process-specific options by default. Refer to
Worker constructor options
to know how to customize worker thread options,
specifically argv
and execArgv
options.