提问者:小点点

NodeJ运行单线程还是多线程?


我读过一些关于NodeJ作为单线程工作的文章。它说nodejs在完成第一个请求后处理第二个请求。所以我试着测试一下。我有一些像这样的代码。然后我依次发送三个请求:

  1. http://localhost:3000/?wait=1:start at 14:29:14.469z
  2. http://localhost:3000/?wait=1:.......14:29:19.496z
  3. http://localhost:3000/:.......14:29:15.725z

我不明白。我想第三次请求应该在14:29:19开始,对吗?或者是我误会了。请为我解释一下,谢谢大家!


共1个答案

匿名用户

Javascript(不仅仅是Node.js,甚至你的web浏览器,不管它是Chrome,Safari,IE还是Edge)都是单线程的。javascript解释器的结构一般可以用以下伪代码来描述:

script_to_exec = compile_js_from_files()

do {

    event_queue = execute_javascript(script_to_exec)

    completed_events = wait_for_events()

    for_each (event from completed_events) {

        this_event = event_queue.find_one_matching(event)

        script_to_exec = this_event.callback
    }

} while (there_is_pending_events)

您可能注意到,上面的代码中根本没有线程代码。我们在wait_for_events()中所做的只是使用OS提供的异步I/O API。根据操作系统的不同,这可以是POSIXselect()或Linux和OSXpoll()或BSDepoll()或Windows重叠I/O函数。Node使用libuv库,该库将在编译时自动选择要使用的最佳API。

好的,循环的第一轮,它执行你的整个代码。这将在您设置Express时设置TCP套接字侦听器。然后它会在wait_for_events()处卡住

第一个HTTP请求导致wait_for_events()返回。这会导致Express遍历您的中间件和路由列表,以找到要执行的路由。它查找路由并调用wait(),后者调用setTimeout(),后者将其回调添加到计时器列表中。

由于在await返回之前没有更多的javascript可执行,我们再次循环,并再次陷入wait_for_events()

第二个HTTP请求导致wait_for_events()返回。这会导致Express遍历您的中间件和路由列表,并重复我前面描述的内容。

由于在await返回之前没有更多的javascript可执行,我们再次循环,并再次陷入wait_for_events()

第三个HTTP请求导致wait_for_events()返回。这会导致Express遍历您的中间件和路由列表,并重复我前面描述的内容。

同样,我们再次循环,并在wait_for_events()处卡住了。

第一个Await wait()计时器过期。这会导致wait_for_events()返回,javascript发现该事件是wait的计时器,因此它继续处理第一个HTTP请求。这会导致Express发送响应。

我们再次循环并等待wait_for_events()

第二个Await wait()计时器到期。这将导致wait_for_events()返回,javascript发现该事件是该wait的计时器,因此它继续处理第二个HTTP请求。这会导致Express发送响应。

我们再次循环并等待wait_for_events()

第三个Await wait()计时器到期。这将导致wait_for_events()返回,javascript发现该事件是wait的计时器,因此它继续处理第三个HTTP请求。这会导致Express发送响应。

我们再次循环,再次在wait_for_events()处停留,等待更多的HTTP请求。。。

基本上javascript可以并行地等待多个东西。这是因为它最初是一种GUI脚本语言,它必须具有等待鼠标单击,键盘输入等操作的能力,但它一次只能执行一条指令(当然,除非您故意使用特性来执行额外的进程/线程,如web workers或worker线程)。

如果您想知道为什么人们将node.js用于高性能web服务器,我已经编写了一个相关问题的答案,解释了为什么node是快速的:node js体系结构和性能

下面是我的一些其他回答,这些回答涉及到异步执行的不同层次的细节:

我知道回调函数是异步运行的,但是为什么呢?

我对异步操作的理解是否正确?

没有无限while循环,还有其他方法实现“监听”功能吗?

节点JS-在回调执行期间传入事件会发生什么

我知道回调函数是异步运行的,但是为什么呢?