Javascript node.js并行执行
我正在努力学习node.js中的并行执行。我写了下面的示例代码。但是,输出是串行的。首先打印0..99,然后打印100..200 我理解这是因为node.js本质上是单线程的,在循环中,线程被for循环捕获 我试图理解的是,在什么情况下,这种Javascript node.js并行执行,javascript,node.js,Javascript,Node.js,我正在努力学习node.js中的并行执行。我写了下面的示例代码。但是,输出是串行的。首先打印0..99,然后打印100..200 我理解这是因为node.js本质上是单线程的,在循环中,线程被for循环捕获 我试图理解的是,在什么情况下,这种流。并行结构是有用的?对I/O或数据库的任何请求在node.js中都是异步的。那我们为什么需要流并行呢 var flow = require('nimble'); flow.parallel([ function a(callback)
流。并行结构是有用的?对I/O或数据库的任何请求在node.js中都是异步的。那我们为什么需要流并行呢
var flow = require('nimble');
flow.parallel([
function a(callback)
{
for(var i=0;i<100;++i)
{
console.log(i);
}
callback();
},
function b(callback)
{
for (var i=100;i<200;++i)
{
console.log(i);
}
callback();
}
]);
var-flow=require('nimble');
平行流动([
函数a(回调)
{
for(var i=0;i在大多数情况下使用这样的并行流,您不会在for循环中打印一组数字(这恰好是阻塞执行)。当您注册函数时,它们的注册顺序与您在传递给parallel
的数组中定义它们的顺序相同。在上述情况下,首先是函数a
,其次是函数b
。因此,节点的事件循环将首先调用a()
,然后是b()
在未公开的时间之后。因为我们知道for循环正在阻塞,并且节点在单个线程中运行,所以它必须在a()
内完成整个for循环,并在节点的事件循环再次控制它之前返回,b()
在队列中等待类似的进程
为什么并行流控制构造有用?根据设计,您不需要在节点内执行阻塞操作(参见您的示例)。a()
消耗整个线程,然后b()
将在其他任何事情发生之前消耗整个线程
a() b()
|
|
|
|
RET
|
|
|
|
RET
现在,假设您正在制作一个web应用程序,用户可以在其中注册并同时上载图片。您的用户注册可能包含以下代码:
var newUser = {
username: 'bob',
password: '...',
email: 'bob@example.com',
picture: '20140806-210743.jpg'
}
var file = path.join(img.IMG_STORE_DIR, newUser.picture);
flow.parallel([
function processImage(callback) {
img.process(function (err) {
if (err) return callback(err);
img.save(file, function (err) {
return callback(err); // err should be falsey if everything was good
})
});
},
function dbInsert(callback) {
db.doQuery('insert', newUser, function (err, id) {
return callback(err);
});
}
], function () {
// send the results to the user now to let them know they are all registered!
});
这里的内部函数是非阻塞的,它们都是在处理或网络负载操作时调用的。但是,它们彼此相当独立。不需要一个函数完成,另一个函数开始。在我们看不到代码的函数中,它们使用了更多异步调用和函数回调,每个函数调用另一项要处理的r节点。节点将尝试清除队列,在CPU周期之间均匀分配工作负载
我们希望这样的事情正在发生:
a = processImage
b = dbInsert
a() b()
|
|
|
|
|
|
|
RET |
RET
如果我们将它们串联在一起,也就是说,在插入db之前,您必须等待图像被完全处理,那么您必须进行大量的等待。如果您的系统上的IO非常高,节点将在操作系统上旋转拇指等待。相比之下,从理论上讲,使用并行将允许慢速操作转为快速操作
如果Node自己做这件事,为什么我们真的需要它呢?关键是在您省略的第二个参数中
nimble.parallel([a,b], function () {
// both functions have now returned and called-back.
});
您现在可以看到,当两个任务都完成时,node默认情况下不会这样做,因此它可能是一件非常有用的事情。flow.parallel
为您提供了可重用的逻辑,用于确定所有并行操作何时完成。是的,如果您刚刚执行了db.query('one');db.query('two');db.query('two');db.query('three'))
,由于异步的性质,它们都将并行执行,但您必须编写一些样板代码来跟踪它们何时完成以及是否遇到错误。正是flow.parallel
(或它在任何流控制库中的对应项)提供的部分。Node.js中的并行执行
使用Nodejs读取并行执行中的文件目录
创建目录
mkdir演示
创建文件
demo.txt、demo2.txt、demo3.txt
每个文件都包含一些内容或段落
创建word_count.js文件
var fs=require('fs');
var completedTasks=0;
var任务=[];
var wordCounts={};
var filesDir='/测试';
函数checkIfComplete(){
已完成任务++;
if(completedTasks==tasks.length){
for(以字数为单位的var索引){
log(索引+':'+字数[index]);
}
}
}
函数countWordsInText(text){
var单词=文本
.toString()
.toLowerCase()
.split(/\W+/)
.sort();
for(大写var指数){
变量词=词[索引];
如果(字){
字数[字]=(字数[字])?字数[字]+1:1;
}
}
}
fs.readdir(filesDir,函数(err,files){
如果(错误)抛出错误;
for(文件中的var索引){
var task=(函数(文件){
返回函数(){
fs.readFile(文件,函数(err,text){
如果(错误)抛出错误;
countsInText(文本);
checkIfComplete();
});
}
})(filesDir+'/'+文件[索引]);
任务。推送(任务);
}
for(任务中的var任务){
任务[任务]();
}
})
它对于在所有并行任务之后执行某些任务非常有用。异步的真正问题不是并行运行某些东西,而是在其他东西之后运行某些东西。请注意,曹兰似乎已经3年没有更新过敏捷。您可以改为查看曹兰/高地。