Node.js维护一个事件循环,但是默认情况下它也有四个复杂请求的线程。当线程池中有更多可用线程时,这是单线程的吗?
此外,复杂任务的事件循环分配的线程是专用线程,那么它与其他多线程概念有何不同?
答案 0 :(得分:7)
在您所指的上下文中,“单线程”表示您的Javascript作为单个线程运行。 没有两个Javascript同时运行字面或时间切片。这大大简化了Javascript开发,因为不需要为不同的Javascript片段之间共享的Javascript变量进行线程同步,因为只有一段Javascript可以同时运行。
所有这一切,node.js确实使用其实现内部的线程。您提到的默认四个线程用于磁盘I / O的线程池。因为磁盘I / O通常是OS级别的同步操作,它阻塞调用线程和node.js的设计,其中所有I / O操作都应作为异步操作提供,node.js设计者决定实现异步接口通过使用线程池来实现(在本机代码中),fs模块磁盘I / O接口(是的,在某些操作系统中有非阻塞磁盘I / O操作,但node.js设计者决定不使用它们)。这一切都发生在本机代码的掩盖之下,并不影响您的Javascript仅在单个线程中运行的事实。
以下是有关磁盘I / O调用如何在node.js中工作的摘要。我们假设已经有一个打开的文件句柄。
fs.write()
。fs.write()
调用fs.write()
调用fs.write()
调用结束。它获取保护事件循环的互斥锁并在事件队列中插入事件。因为在当前的Javascript流完成执行之前从未对新事件起作用,所以Javascript获取的是事件驱动的单线程性质,即使本机代码线程可用于实现某些库函数。这些线程用于将阻塞操作转换为非阻塞操作,但不会影响Javascript执行本身的单线程。
这里的关键是node.js是事件驱动的。触发某些Javascript运行的每个新操作都是通过事件队列序列化的,并且在当前的Javascript流完成执行之前,不会为下一个事件提供服务。
在node.js体系结构中,让两个Javascript独立运行并同时运行的唯一方法是为每个部分使用单独的node.js进程。然后,它们将作为两个完全独立的操作运行,操作系统将分别管理它们。如果您的计算机至少有两个核心,那么它们可以在同一时间运行,每个核心都在自己的核心上运行。如果您的计算机只有一个核心,它们将基本上位于自己的进程线程中,操作系统将对它们进行时间分片(在它们之间共享一个CPU)。
答案 1 :(得分:2)
默认情况下,执行您的JavaScript代码会在单个线程上运行。
但是,node.js尝试将大多数长时间运行的调用设为异步。对于一些只涉及执行异步OS调用的人,但对于其他一些人来说,node.js将在辅助线程上执行调用,同时继续运行其他JS代码。异步调用终止后,Js回调或Promise处理程序将运行。
答案 2 :(得分:1)
对于异步处理,Node.js 是作为实验明确创建的。与典型的基于线程的实现相比,在典型的 Web 负载下对单个线程进行异步处理可以实现更高的性能和可扩展性。