因此,我正在阅读一些有关nodejs的内容,当我遇到Worker Threads时感到惊讶。
我认为拥有线程是一个很好的选择,尤其是将线程与共享内存访问结合使用时。您可能已经想过-> SharedArrayBuffer
...
是的,这就是我的想法。因此,我想到的第一件事就是进行一些测试,然后尝试实现一个简单的store
(目前是一个简单的对象),该线程将在线程之间共享。
问题是,(除非我在这里不遗漏什么)如何使用SharedArrayBuffer
使对象可以从n个线程访问?
我知道对于一个简单的Uint32Array
来说是可行的,但是关于对象该怎么办?
起初,我想将其转换为Uint32Array
,就像您可能看到的那样,但是即使查看该死的源代码也让我想哭...
const {
Worker,
isMainThread,
workerData
} = require('worker_threads');
const store = {
ks109: {
title: 'some title 1',
description: 'some desciption 1',
keywords: ['one', 'two']
},
ks110: {
title: 'some title 2',
description: 'some desciption 2',
keywords: ['three', 'four']
},
ks111: {
title: 'some title 3',
description: 'some desciption 3',
keywords: ['five', 'six']
}
}
const shareObject = (obj) => {
let OString = JSON.stringify(obj);
let SABuffer = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * OString.length);
let sArray = new Int32Array(SABuffer);
for (let i = 0; i < OString.length; i++) {
sArray[i] = OString.charCodeAt(i);
}
return sArray;
}
if (isMainThread) {
const sharedStore = shareObject(store);
console.log('[Main][Data Before]:', sharedStore.slice(-10));
let w = new Worker(__filename, {
workerData: sharedStore
});
w.on('message', (msg) => {
console.log(`[Main][Thread message]: ${msg}`);
});
w.on('error', (err) => {
console.error(`[Main][Thread error] ${err.message}`);
});
w.on('exit', (code) => {
if (code !== 0) {
console.error(`[Main][Thread unexpected exit]: ${code}`);
}
});
setInterval(() => {
// At some point you ll see a value change,
// it's 'six' becoming 'sax' (big time!)
console.log('[Main][Data Check]:', sharedStore.slice(-10));
}, 1000);
} else {
let str = String.fromCharCode.apply(this, workerData);
let obj = JSON.parse(str);
obj.ks111.keywords[1] = 'sax'; // big time!
let OString = JSON.stringify(obj);
for (let i = 0; i < OString.length; i++) {
workerData[i] = OString.charCodeAt(i);
}
}
最后,nodejs 10.5.0中的线程之间共享对象,这可能吗?怎么样?
答案 0 :(得分:3)
ECMA脚本不包含共享对象。但是您可以使用DataView和包装器直接在缓冲区中写入数据来实现这种行为:
// Shared value
class SharedPoint {
constructor(array) {
this.dataview = new DataView(array);
}
set x(value) {
this.dataview.setUint8(0, value);
}
set y(value) {
this.dataview.setUint8(1, value);
}
get x() {
return this.dataview.getUint8(0);
}
get y() {
return this.dataview.getUint8(1);
}
}
// Usage
const buffer = new SharedArrayBuffer(2);
// Create two instances of shared point.
const pointA0 = new SharedPoint(buffer);
const pointA1 = new SharedPoint(buffer);
// Get initial values for point A1
console.log('x', pointA1.x); // 0
console.log('y', pointA1.y); // 0
// Update point A0
pointA0.x = 64;
pointA0.y = 32;
// Get changes in point A1
console.log('x', pointA1.x); // 64
console.log('y', pointA1.y); // 32
您可以创建可以操纵字符串或C-like structures的类。虽然SharedArrayBuffer是可转移的对象,但它可以在工作进程和主进程之间共享。
请注意,由于Spectre attack,SharedArrayBuffer已被所有主要的浏览器禁用,并在可能的情况下从版本67开始在Chrome中重新启用。