【问题标题】:Do Timers run on their Own threads in Node.js?计时器是否在 Node.js 中的自己的线程上运行?
【发布时间】:2020-09-21 17:03:40
【问题描述】:

我在这里有点困惑,我知道 Javascript 是一种单线程语言,但在阅读事件循环时。我知道,在 setTimeout 或 setInterval javascript 调用浏览器提供的 Web API 的情况下,它会生成一个新线程来在该线程上执行计时器。但是在带有计时器的 node.js 环境中会发生什么情况?它们如何执行/工作?

【问题讨论】:

  • 注意:nodejs 不是用 javascript 编写的。

标签: javascript node.js


【解决方案1】:

node.js 中没有线程用于计时器。

node.js 中的计时器与事件循环一起工作,不使用线程。 node.js 中的计时器存储在排序的链表中,下一个计时器在链表的开头触发。每次通过事件循环时,它都会检查链表中的第一个计时器是否已到达其时间。如果是这样,它会触发该计时器。如果没有,它会运行在事件循环中等待的任何其他事件。

在事件循环的每个后续循环中,它会不断检查是否为下一个计时器计时。添加新计时器时,它会按照正确的排序顺序插入到链表中。当它触发或被取消时,它会从链表中移除。

如果事件循环无事可做,它可能会休眠一小段时间,但它不会休眠到下一个定时器的定时器。

关于该主题的其他参考资料:

How does nodejs manage timers internally

Libuv timer code in nodejs

How many concurrent setTimeouts before performance issues?

Multiple Client Requests in NodeJs

Looking for a solution between setting lots of timers or using a scheduled task queue

【讨论】:

    【解决方案2】:

    没有。计时器只是安排在同一个线程上,并在时间到期时调用它们的回调。

    根据您使用的操作系统和您使用的 javascript 解释器,他们将使用从 poll 到 epoll 到 kqueue 的各种 API 在 Windows 上重叠 I/O,但通常异步 API 具有相似的功能。所以让我们忽略平台差异,看看所有操作系统上都存在的跨平台 API:POSIX select() 系统调用。

    C 中的select 函数看起来像这样:

    int select(int nfds, fd_set *readfds, fd_set *writefds,
                  fd_set *exceptfds, struct timeval *timeout);
    

    nfds 是您正在等待/侦听的文件描述符(包括网络套接字)的总数,readfds 是您正在等待的读取文件描述符的列表/集,writefds 是列表/集在写入文件描述符中,exceptfds 是错误文件描述符的列表/集(想想 stderr),timeval 是函数的超时时间。

    这个系统调用阻塞 - 是的,在非阻塞异步代码中有一段阻塞系统调用。非阻塞代码和阻塞线程代码的主要区别在于,整个程序只在一个地方阻塞,select() 函数(或您使用的任何等效函数)。

    此函数仅在任何文件描述符上有活动或超时到期时才返回。

    通过管理超时和计算timeval 的下一个值,您可以实现类似setTimeout 的函数

    我已经在回答以下相关问题时对它的工作原理进行了更深入的解释:

    I know that callback function runs asynchronously, but why?

    Event Queuing in NodeJS

    how node.js server is better than thread based server

    Node js architecture and performance

    Performance of NodeJS with large amount of callbacks

    Does javascript process using an elastic racetrack algorithm

    Is there any other way to implement a "listening" function without an infinite while loop?

    我建议您至少浏览一下我上面写的每个答案,因为它们几乎都是非重复的。它们有时重叠,但解释了异步代码执行的不同方面。

    它的要点是 javascript 不会并行执行代码来实现计时器。它不需要。相反,它等待并行。一旦您了解了并行运行代码和并行等待(什么都不做)之间的区别,您将了解 node.js 之类的东西如何实现高性能以及事件如何更好地工作。

    【讨论】:

      【解决方案3】:

      节点在单个线程上运行,但异步工作发生在其他地方。例如,libuv 提供了一个可以使用的 4 个线程池,但如果有更好的选择则不会。

      节点documentation 说

      Node.js 在事件循环(初始化和回调)中运行 JavaScript 代码,并提供一个工作池来处理文件 I/O 等昂贵的任务。 Node.js 可以很好地扩展,有时比 Apache 等更重量级的方法更好。 Node.js 可扩展性的秘诀在于它使用少量线程来处理许多客户端。如果 Node.js 可以使用更少的线程,那么它可以将更多的系统时间和内存花费在客户端上,而不是为线程(内存、上下文切换)支付空间和时间开销。但是因为 Node.js 只有几个线程,所以您必须构建应用程序以明智地使用它们。

      多detailed看看事件循环

      【讨论】:

      • 这是正确的,但根本没有涉及计时器的线程。文档明确指出线程仅用于四件事:磁盘 I/O、DNS 解析器(在大多数操作系统上没有异步 API)、zip 和 gzip 压缩以及一些加密功能
      猜你喜欢
      • 2021-05-10
      • 1970-01-01
      • 2010-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-03
      • 1970-01-01
      相关资源
      最近更新 更多