有关nodejs线程的一些混淆

我有一些关于nodejs线程的混淆。

据我所知, nodejs运行在一个单一的线程。 如果有一个asynchronous函数被调用, nodejs将创build一个新的线程来运行这些asynchronous代码。 asynchronous代码完成后。 event loop将获得asynchronous结果,并在另一个新线程中触发callback函数。

为了testing,我进行了下面的代码testing:

 var fs = require("fs"); fs.readFile('package.json','utf-8', function (err, data) { if(err) console.log(err) else console.log(data); }); console.log("before loop"); while(true); console.log("after loop"); 

我的预期结果是:

循环之前
– package.json内容 –

其实得到:

循环之前

我可能在一些地方是错的。

问题

  1. 为什么while(true)阻塞了readFile()或阻止了它的callback函数?
  2. 这些线程之间有什么关系?

你是正确的,在nodejs运行在一个单一的线程。 您可以启动单独的进程,并在这些进程之前放置一个负载平衡器以利用多核处理器,但是这不会在节点本身中实现。

但是,节点不会为每个遇到的asynchronous函数启动一个线程。 它将这些函数调用放入不断运行的事件循环中。 这里最重要的是事件循环是非阻塞的,这意味着函数调用的执行顺序是不能保证的 – 这就是callback是所有node.js程序的基础。 这意味着,例如,当一个函数正在等待在文件系统中find文件并读取到缓冲区时,事件循环不会停止所有事情,等待它完成并继续下一个调用。 但绝不是这种multithreading行为。 事件循环不是并行执行任何事情,只是不断地在任务之间切换。 这只是多任务:)

在你的例子中,while(true)阻塞事件循环,因为它不是一个asynchronous函数调用。 不要忘记,不是所有的javascript都是asynchronous的 – 只有函数调用可以是asynchronous的,而不是其他语言的结构,比如循环或者条件。 所以在你的例子中,你运行了添加到事件循环并启动的asynchronous文件阅读器。 当文件系统正在做这件事时,事件循环无关紧要,并转到console.log(“before loop”)消息。 之后,用while(true)循环阻塞事件循环。 这意味着事件循环不能将其搁置并再次转到文件读取器。

希望这能说明问题。 这里主要的一点是并不是所有的javascript都是asynchronous的,但是处理不同设备(比如文件系统或者networking)的大多数耗时的操作都是以非阻塞的方式实现的。 asynchronous函数只有在使用某个外部组件时才有意义 – 您不会使用asynchronous平方根函数,因为它会阻止事件循环。 这就是为什么不推荐node.js用于繁重的计算操作(如audio/video编码)的原因 – asynchronous优势在这里没有意义。

我在这里find了一些其他很棒的答案:

此callback函数的调用作为调用堆栈中的初始帧,并且由于JavaScript是单线程的,所以进一步的消息轮询和处理在堆栈上的所有调用返回之前暂停。 随后的(同步)函数调用将新的调用帧添加到堆栈(例如,函数init调用函数changeColor)。

这又解决了我的困惑! 我现在更清楚了!