The basic information
The author tested this feature on the latest development version of Node.js, v11.4.0. Currently, it is necessary to add flags to introduce Worker Threads, for example:
node --experimental-worker index.js
Copy the code
The Worker Threads feature was introduced in v10.5.0 on June 20, 2018:
node/CHANGELOG
At present, the module is in the Stability 1-experimental stage, which will undergo large changes and is not recommended to be used in production environment.
Module interface
const {
isMainThread, parentPort, workerData, threadId,
MessageChannel, MessagePort, Worker
} = require('worker_threads');
Copy the code
The module has very few objects and classes, only four objects and three classes.
isMainThread
: false indicates the current worker thread,false
Represents the main threadparentPort
: refers to the parent process in worker threadsMessagePort
Object of type, as in the main threadnull
workerData
In the worker thread, is the initialization data of the parent process when creating the worker thread. In the main thread, is the initialization data of the parent processundefined
threadId
: is the thread ID in worker threads and is the thread ID in parent processes0
.MessageChannel
: contains two threads that can already communicate with each otherMessagePort
Type object that can be used to create a custom communication channel, as shown in Example 2.MessagePort
: handle for cross-thread communication, inheritedEventEmitter
, including the Close Message event to receive messages that an object closes and sends, and operations such as close postMessage.Worker
The main thread is the object type used to create worker threads, including all MessagePort operations and some unique meta data operations for child threads. The first argument to the constructor is an entry script executed by the child thread, and the second argument contains configuration items that specify some initial arguments. For details, seeThe document
Changes to the memory model
SharedArrayBuffer is typically used when using Cluster and Child_process to implement memory that needs to be shared by multiple processes.
port.postMessage(value[, transferList])
Copy the code
Now the Worker Threads module does not recommend multithreading shared memory at the API layer. The value of the first parameter is cloned by the thread receiving the message. TransferList can only pass an ArrayBuffer or a MessagePort object. Passing an ArrayBuffer modifies the access permission of the Buffer to the thread receiving the message. For example, see Example 2.
All cross-thread message communication is implemented through the low-level V8 serialization, with the more specific Worker Threads and V8 multi-threading models and their relationship to the browser’s Web Worker standard being left unexplored.
Example 1: Count the communication between the main thread and the worker thread. When the count reaches 5, the worker thread commits suicide
const {
isMainThread, parentPort, workerData, threadId,
MessageChannel, MessagePort, Worker
} = require('worker_threads');
function mainThread() {
const worker = new Worker(__filename, { workerData: 0 });
worker.on('exit', code => { console.log(`main: worker stopped with exit code ${code}`); });
worker.on('message', msg => {
console.log(`main: receive ${msg}`);
worker.postMessage(msg + 1);
});
}
function workerThread() {
console.log(`worker: threadId ${threadId} start with ${__filename}`);
console.log(`worker: workerDate ${workerData}`);
parentPort.on('message', msg => {
console.log(`worker: receive ${msg}`);
if (msg === 5) { process.exit(); }
parentPort.postMessage(msg);
}),
parentPort.postMessage(workerData);
}
if (isMainThread) {
mainThread();
} else {
workerThread();
}
Copy the code
Output result:
worker: threadId 1 start with /Users/azard/test/index.js
worker: workerDate 0
main: receive 0
worker: receive 1
main: receive 1
worker: receive 2
main: receive 2
worker: receive 3
main: receive 3
worker: receive 4
main: receive 4
worker: receive 5
main: receive 5
main: worker stopped with exit code 0
Copy the code
Example 2: Use a MessageChannel to let two child threads communicate directly
const {
isMainThread, parentPort, workerData, threadId,
MessageChannel, MessagePort, Worker
} = require('worker_threads');
if (isMainThread) {
const worker1 = new Worker(__filename);
const worker2 = new Worker(__filename);
const subChannel = new MessageChannel();
worker1.postMessage({ hereIsYourPort: subChannel.port1 }, [subChannel.port1]);
worker2.postMessage({ hereIsYourPort: subChannel.port2 }, [subChannel.port2]);
} else {
parentPort.once('message', (value) => {
value.hereIsYourPort.postMessage('hello');
value.hereIsYourPort.on('message', msg => {
console.log(`thread ${threadId}: receive ${msg}`);
});
});
}
Copy the code
Output:
thread 2: receive hello
thread 1: receive hello
Copy the code
conclusion
Now that Node.js has true multithreading, there is no need to use cluster or child_process to handle some problems, and the related framework and library model can also start to iterate after Worker Threads stabilize.