如果 Node.js 是单线程的,那么如何处理并发?
Node js 是一个使用 javascript 作为脚本语言的开源虚拟机。尽管是单线程的,但它是最流行的 Web 技术之一。尽管 node js 是单线程的,但它之所以受欢迎,是因为它的异步特性使得处理并发和同时执行多个 I/O 操作成为可能。 Node js 使用事件循环来维护并发并执行非阻塞 I/O 操作。
一旦 Node js 启动,它就会初始化一个事件循环。事件循环在队列(称为事件队列)上工作,并以 FIFO(先进先出)顺序执行任务。它仅在调用堆栈中没有正在进行的任务时才执行任务。调用堆栈以 LIFO(后进先出)顺序工作。事件循环不断检查调用堆栈以检查是否有任何任务需要运行。现在,每当事件循环找到任何函数时,它都会将其添加到堆栈中并按顺序运行。
让我们看一个例子来正确理解如何调用堆栈和事件循环以及如何处理并发,
示例 1:在此示例中,我们将看到调用堆栈的工作情况。
Javascript
Javascript
输出:
Two times the number 5 is 10
说明:这里,当代码执行时,函数print(5) 将被调用并压入调用堆栈。当该函数被调用时,它开始对其中的语句进行合并,但在合并整个语句之前,它遇到另一个函数add(n,n) 并暂停其当前执行,并将 add函数推入调用堆栈的顶部。现在该函数将返回加法 a+b 然后从堆栈中弹出,现在先前挂起的函数将开始运行并将输出记录到控制台,然后该函数也将从堆栈中弹出,现在堆栈为空.这就是调用堆栈的工作方式。
示例 2:在此示例中,我们将看到事件循环的工作原理。
Javascript
输出:
Statement outside function
Statement 1 inside function
Statement 3 inside function
Statement 2 inside function
解释:在上面的例子中。第一个控制台语句“statement outside 函数”将被推入堆栈并登录到控制台并从堆栈中弹出。现在函数func() 将被调用并压入堆栈。然后语句 1“Statement 1 inside 函数”将被推送并记录到控制台并从堆栈中弹出。然后运行时进入 setTimeout()函数,因为这是一个 Web API,所以它进入浏览器,现在浏览器将设置计时器并执行它,然后它从堆栈中弹出,同时下一条语句开始调用堆栈和因此“函数内的语句 3”将打印到控制台。现在,当 2 秒(2000 毫秒)完成时,浏览器会将函数推回事件队列。现在事件循环检查调用堆栈是否为空,然后将函数推入调用堆栈,“函数内部的语句 2”将打印到控制台,函数将从堆栈中弹出。现在函数已经完成,没有更多的事件了。
这就是通过使用事件循环和调用堆栈来实现并发的方式。