我一直在关注并发性和并行性之间的区别。我在Rob上发表了一篇关于并发和并行之间差异的话题。他的演讲是在Google Go语言的背景下进行的。根据我的理解,并发性是能够处理多个事物的设计,但并行性是同时多个事物的物理执行。
根据我的理解,Node.js作为单个线程进程运行。因此,尽管Node通过实现回调等方式支持并发,它是否能够处理任务的并行执行?它可以设置为在不同的处理器上运行多个线程吗?
答案 0 :(得分:8)
Node可以通过Nodejs Core API中打包的Cluster
或child_process
模块支持“Parallelism”。这两个模块都创建了额外的进程而不是其他线程。
创建和管理线程,有时在池中,由libuv
node
实现“引擎盖”,libuv
实现并用于执行异步操作,例如从文件读取。 您无法从执行的Javascript中明确创建线程。您可以在以下资源中详细了解libuv
libuv
API Docs libuv
book libuv
(Cluster
本书的一部分)此外,这是Threads and Pooling的一个很好的问题,它有很多细节。
Cluster
用于将服务器的工作负载分布在多个核心上,并且仍然让它们共享一个端口。但是,child_process.fork()
使用libuv
并通过inter-process communication进行通信。您可以阅读有关Cluster
in the Nodejs Core API Docs的更多信息。
child_process
提供了几种通过exec()
,spawn()
或fork()
并行工作的方法。父进程可以通过管道使用进程间通信与子进程通信。
基本上,Node希望您利用the event loop并将线程管理留给child_process
。这就是为什么构建通常需要锁定和线程安全措施的代码非常容易的原因。如果您必须完成需要繁重工作或大量阻塞(同步)工作的工作,那么您可以使用Cluster
来卸载该工作。如果您需要跨核心扩展Web应用,请使用localStorage
。
答案 1 :(得分:1)
如果我没有弄错的话,你就是在寻找多线程和/或同时计算多件事情的东西。
一次多次执行
SIMD开始进入浏览器,Node实现也不甘落后。请查看node-simd或MDN SIMD (browsers)。
SIMD仍处于试验阶段,目前仅适用于受支持的CPU(显然,因为并非所有CPU都具有此功能)。它一次执行多个事情,比较普通JS和SIMD JS的例子是:
// Normal addition, 4 actions are executed.
var a = [1, 2, 3, 4];
var b = [5, 6, 7, 8];
var c = [];
c[0] = a[0] + b[0];
c[1] = a[1] + b[1];
c[2] = a[2] + b[2];
c[3] = a[3] + b[3];
c; // Array[6, 8, 10, 12]
// SIMD execution - all additions are processed simultaenously through the CPU
var a = SIMD.Float32x4(1, 2, 3, 4);
var b = SIMD.Float32x4(5, 6, 7, 8);
var c = SIMD.Float32x4.add(a,b);
c; // Float32x4[6, 8, 10, 12]
<强>多线程强>
关于多线程,webworkers
已经存在于浏览器环境中一段时间了。这已根据HTML规范in this repository完全移植到Node
这里&#39; sa good explanation关于为什么webworkers
首先被移植到Node,因为您已经可以在其他线程和其他具有child_process
模块的CPU上运行子进程。 node-webworker
是一个很棒的模块,因为每个进程都在其上下文中运行,并且在它自己的node
进程中,所以它是真正的多线程节点。
因此,要在不同的CPU上运行不同的进程,您可以采用node-webworker
或使用child_process
来生成其他线程,以便使用不同的CPU内核同时执行单独的操作。 node-webworker
可以使用熟悉的postMessage
API来监听活动,child_process
将通过stdin / stdout / stderr
进行通信。
希望能回答你的问题:)
答案 2 :(得分:0)
可以通过利用本机节点os
和cluster
模块来在一台主机上的单独处理器中运行多个线程。以下是一个简单的示例
const cluster = require('cluster');
const os = require('os');
((port) => {
if (cluster.isMaster) {
// fork the process
os.cpus().forEach((cpu) => {
cluster.fork();
});
} else {
// if we're not in the master thread, start the HTTP server
http.createServer((req, res) => {
// Handle request
}).listen(port, () => {
console.log(`The server is listening on port ${port}`);
});
}
})(3000)