Node.js 多线程完全指南总结

2020-06-17 06:09:52易采站长站整理

请注意,在后面的例子中,为了简便起见,我用了

parentPort

使用 worker 的两种方式

可以通过两种方式使用 worker。第一种是生成一个 worker,然后执行它的代码,并将结果发送到父线程。通过这种方法,每当出现新任务时,都必须重新创建一个工作者。

第二种方法是生成一个 worker 并为

message
事件设置监听器。每次触发
message
时,它都会完成工作并将结果发送回父线程,这会使 worker 保持活动状态以供以后使用。

Node.js 文档推荐第二种方法,因为在创建 thread worker 时需要创建虚拟机并解析和执行代码,这会产生比较大的开销。所以这种方法比不断产生新 worker 的效率更高。

这种方法被称为工作池,因为我们创建了一个工作池并让它们等待,在需要时调度

message
事件来完成工作。

以下是一个产生、执行然后关闭 worker 例子:


import { parentPort } from 'worker_threads';

const collection = [];

for (let i = 0; i < 10; i += 1) {
collection[i] = i;
}

parentPort.postMessage(collection);

collection
发送到父线程后,它就会退出。

下面是一个 worker 的例子,它可以在给定任务之前等待很长一段时间:


import { parentPort } from 'worker_threads';

parentPort.on('message', (data: any) => {
const result = doSomething(data);

parentPort.postMessage(result);
});

worker_threads 模块中可用的重要属性

worker_threads
模块中有一些可用的属性:

isMainThread

当不在工作线程内操作时,该属性为

true
。如果你觉得有必要,可以在 worker 文件的开头包含一个简单的
if
语句,以确保它只作为 worker 运行。


import { isMainThread } from 'worker_threads';

if (isMainThread) {
throw new Error('Its not a worker');
}

workerData

产生线程时包含在 worker 的构造函数中的数据。


const worker = new Worker(path, { workerData });

在工作线程中:


import { workerData } from 'worker_threads';

console.log(workerData.property);

parentPort

前面提到的

MessagePort