1. 程式人生 > 其它 >關於 NODE.js 並行執行緒 worker_threads 的使用與詳解。

關於 NODE.js 並行執行緒 worker_threads 的使用與詳解。

技術標籤:javascriptnode.js服務端nodejs多執行緒javascript執行緒併發

javascript 是單執行緒,那麼node.js屬於服務端語言改如何實現其他語言中的併發執行緒執行呢?在node V10只有 child_process,cluster的API來開啟多子程序,多程序。程序並不是子執行緒,無法記憶體共享。在nodeV10後引入worker_threads API概念。

worker_threads

node官方文件註明了:

  • worker_threads 模組允許使用並行地執行 JavaScript 的執行緒。
  • 與 child_process 或 cluster 不同, worker_threads 可以共享記憶體。 它們通過傳輸 ArrayBuffer 例項或共享 SharedArrayBuffer 例項來實現。

所以我們看到worker_threads作用類似其他語言中的子執行緒併發執行,首先我們執行兩段程式碼使用worker_threads和不使用worker_threads的區別。

模擬一個cpu密集計算 http 服務

const http = require('http')

const fork = () => {
    const startTime = new Date().getTime()
    for(let i = 0; i < 1000000000; i ++) {}
    const endTime = new Date().getTime()
    return `運算1000000000次,開始運算時間:
${startTime},結束運算時間${endTime}`
} const server = http.createServer((request, response) => { if(request.url === '/') { const result1 = fork() // 運算第一次 const result2 = fork() // 運算第二次 response.setHeader('content-Type', 'text/html; charset=utf-8') response.statusCode =
200 response.end(`${result1} \n ${result2}`, 'utf-8') } }) server.listen(8080, () => { console.log('啟動成功') })
然後我們開啟瀏覽器訪問 http://localhost:8080/

在這裡插入圖片描述

我們可以看到運算結果是依次進行的。那麼我們來使用worker_threads進行優化看看結果

把程式中的密集計算工作提煉到另一個worker.js文中,因為worker_threads是以js檔案來執行的。

// worker.js
const { parentPort } = require('worker_threads')

const startTime = new Date().getTime()
for(let i = 0; i < 1000000000; i ++) {}
const endTime = new Date().getTime()

parentPort.postMessage(`運算1000000000次,開始運算時間:${startTime},結束運算時間${endTime}`)
// http.js 修改
const http = require('http')
const { join } = require('path')
const { Worker } = require('worker_threads')

const server = http.createServer((request, response) => {
    if(request.url === '/') {
        response.setHeader('content-Type', 'text/html; charset=utf-8')
        response.statusCode = 200

        const wk1 = new Worker(join(__dirname, './worker.js'))
        const wk2 = new Worker(join(__dirname, './worker.js'))

        let result = ''
        const success = res => {
            if (result) // 判斷是否已經接收到一次結果
                response.end(`${result} <br /> ${res}`, 'utf-8')
            else
                result = res
        }

        wk1.on('message', success)
        wk2.on('message', success)
    }
})

server.listen(8080, () => {
    console.log('啟動成功')
})

訪問http://localhost:8080/ 響應
在這裡插入圖片描述
從響應結果我們可以看到,兩次運算都是併發執行的。上面parentPort API進行父級通訊的api。具體更多api和使用大家可以到node官網進行了解