Skip to content
导航

worker_threads

不同于 child_process 、cluster 是创建子进程,worker_threads 是创建线程,它们共享进程所有的内存,因此相比多进程可以节省内存。

多线程对于执行 CPU 密集型 JavaScript 操作能起到并行效果,而对I/O密集型任务没有帮助。

worker_threads 的用法和浏览器端 Worker 相似但不同。

下面的代码导出一个模块,模块内创建线程来处理任务,并异步返回内容

js
const {
  Worker,
  isMainThread,
  parentPort,
  workerData,
} = require('node:worker_threads')

if (isMainThread) {
  module.exports = function clonseJSAsync(obj) {
    return new Promise((resolve, reject) => {
      const worker = new Worker(__filename, {
        workerData: obj,
      })
      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 deepClone = (obj) => JSON.parse(JSON.stringify(obj))
  const obj = workerData
  parentPort.postMessage(deepClone(obj))
}

模块的作用是简单地深拷贝对象。

使用这个模块,对比不使用 worker_threads 进行深拷贝对象的耗时

js
const threadsClone = require('./worker')
const data = require('./enemy')

console.time('single clone')
for (let i = 0; i < 100; i++) {
  JSON.parse(JSON.stringify(data))
}
console.timeEnd('single clone')

console.time('threads clone')
const promises = []
for (let i = 0; i < 100; i++) {
  promises.push(threadsClone(data))
}
Promise.all(promises).then(() => {
  console.timeEnd('threads clone')
})

在4核心电脑上,运行输出如下:

single clone: 37.17ms
threads clone: 1.890s

显然,创建 Worker 的开销超过了多线程的收益。

实际使用中会使用线程池,复用创建的固定数量的Workers,来完成任务。即通过编程的方式实现 cluster 那样进行多线程的负载均衡。

参考资料