下面详细讲解如何在Node.js中使用worker_threads
模块来创建新线程。
简介
在Node.js中,JavaScript语言具有单线程执行的特性,这意味着如果主线程执行某些任务时,会阻塞其他任务的执行进度,导致性能瓶颈。因此,可以使用worker_threads
模块创建新线程,实现多线程执行任务的目的。Worker对象执行的代码并不在主线程中运行,所以它们不会阻塞主线程。
创建Worker
使用worker_threads
模块创建Worker的基本语法如下:
const { Worker } = require('worker_threads');
const worker = new Worker(workerDataFile, options);
其中,workerDataFile
是一个要在工作线程中运行的JS文件,而options
是Workers工作条件的配置项。这样就可以创建出一个新的Worker对象,可以在这个对象上调用一些方法控制它的行为。
Worker线程的生命周期
创建Worker后,会自动创建一个新线程来执行传入的workerDataFile
代码,直到它停止或被终止。Worker线程的完整生命周期如下:
new Worker()
:创建Worker对象;Worker.on('message', message => {})
:监听Worker线程发送的消息;Worker.on('error', error => {})
:监听Worker线程的错误;Worker.on('exit', code => {})
:监听Worker线程的退出;Worker.postMessage()
:向Worker线程发送消息;Worker.terminate()
:立即关闭Worker线程。
示例1:异步计算
我们来看一个Worker的示例。在这个示例中,我们创建了一个用于计算斐波那契数列的Worker。
创建一个名为calFibonacci.js
的文件,代码如下:
const { parentPort } = require('worker_threads');
function fibonacci(n) {
if (n === 0 || n === 1) {
return n;
} else {
return fibonacci(n-1) + fibonacci(n-2);
}
}
parentPort.on('message', (num) => {
const result = fibonacci(num);
parentPort.postMessage(result);
});
上述代码中,我们从worker_threads
模块中引入parentPort
对象,在这个对象上监听由主线程发来的消息。当我们收到一条消息时,就会计算斐波那契数列并将结果通过parentPort.postMessage()
方法发送回主线程。
接下来,我们在主线程中创建Worker。
const { Worker } = require('worker_threads');
const path = require('path');
const worker = new Worker(path.join(__dirname, 'calFibonacci.js'));
worker.on('message', (result) => {
console.log('计算结果:', result);
});
const num = 40;
worker.postMessage(num);
console.log('主线程计算中...');
上述代码中,我们使用path.join()
方法创建Worker的workerDataFile
参数,将斐波那契数列计算的工作交给Worker线程。当Worker线程完成计算后,会将结果通过worker.postMessage()
方法发送回来。在主线程中,我们通过监听Worker的message
事件来获取计算结果。执行这段代码后,可以看到如下输出:
主线程计算中...
计算结果: 102334155
可见,Worker线程成功地完成了斐波那契数列的计算并返回了结果。
示例2:文件读写
我们可以在Worker线程中完成磁盘IO等阻塞式操作,并让主线程继续执行不相关的工作。例如,一个计算密集型的应用程序可在一个Worker中运行而在主线程中处理IO。
在这个示例中,我们将创建一个文件读写工具,用于读取文件并将其内容写入新文件。我们将创建一个名为fileIO.js
的文件用于处理此任务。
const fs = require('fs');
const { parentPort } = require('worker_threads');
const fileIO = (inputFilePath, outputFilePath) => {
const readStream = fs.createReadStream(inputFilePath, { encoding: 'utf-8' });
const writeStream = fs.createWriteStream(outputFilePath, { encoding: 'utf-8' });
readStream.on('error', error => {
console.error(`读取文件 '${inputFilePath}' 失败`, error);
parentPort.postMessage({
status: 'failed',
msg: `读取文件 '${inputFilePath}' 失败`
});
});
writeStream.on('error', error => {
console.error(`写入文件 '${outputFilePath}' 失败`, error);
parentPort.postMessage({
status: 'failed',
msg: `写入文件 '${outputFilePath}' 失败`
});
});
writeStream.on('close', () => {
parentPort.postMessage({
status: 'success',
inputFilePath,
outputFilePath
});
});
readStream.pipe(writeStream);
};
parentPort.on('message', (data) => {
const { inputFilePath, outputFilePath } = data;
fileIO(inputFilePath, outputFilePath);
});
上述代码中,我们从worker_threads
模块中引入parentPort
对象,接收由主线程发来的消息。当我们收到一条消息时,会将读取的文件结果写入新文件。如果其中任何一步操作出错,就向主线程发送一个消息。
接下来,我们在主线程中创建Worker。
const { Worker } = require('worker_threads');
const path = require('path');
const worker = new Worker(path.join(__dirname, 'fileIO.js'));
worker.on('message', (result) => {
console.log(result);
});
const inputFilePath = path.join(__dirname, 'input.txt');
const outputFilePath = path.join(__dirname, 'output.txt');
worker.postMessage({
inputFilePath,
outputFilePath
});
console.log(`开始读写文件, input文件路径: ${inputFilePath}, output文件路径: ${outputFilePath}`);
上述代码中,我们使用path.join()
方法创建Worker的workerDataFile
参数,将文件读写的操作交给Worker线程。当Worker线程完成任务后,会将结果通过worker.postMessage()
方法发送回来。在主线程中,我们通过监听Worker的message
事件来获取计算结果。执行这段代码后,可以看到如下输出:
开始读写文件, input文件路径: /usr/local/nodeproject/input.txt, output文件路径: /usr/local/nodeproject/output.txt
{ status: 'success',
inputFilePath: '/usr/local/nodeproject/input.txt',
outputFilePath: '/usr/local/nodeproject/output.txt' }
可见,Worker线程成功地完成了文件读写任务,并成功的写入了新文件,同时向主线程发送了成功的消息。
以上就是关于如何在Node.js中使用worker_threads
模块来创建新线程的详细攻略,希望可以对你有所帮助。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:nodejs中使用worker_threads来创建新的线程的方法 - Python技术站