Javascript Node JS单线程与多线程(CPU利用率:有什么区别?)

Javascript Node JS单线程与多线程(CPU利用率:有什么区别?),javascript,node.js,multithreading,Javascript,Node.js,Multithreading,最近我开始阅读很多关于Node JS的文章,从差异化的角度来看,有一件事我不能清楚地理解,异步调用和同步调用处理I/O的方式之间的真正区别是什么 据我所知,在多线程同步环境中,如果启动I/O,正在运行的线程将被抢占并移回等待状态。因此,本质上这与NodeJS异步I/O调用的情况相同。在Node JS中,当调用I/O时,I/O操作将移出当前运行的线程,并发送到事件解复用器以完成和通知。I/O完成后,回调方法将被推送到事件队列进行进一步处理 因此,我看到的唯一区别是,在Node JS中,我们节省了内

最近我开始阅读很多关于Node JS的文章,从差异化的角度来看,有一件事我不能清楚地理解,异步调用和同步调用处理I/O的方式之间的真正区别是什么

据我所知,在多线程同步环境中,如果启动I/O,正在运行的线程将被抢占并移回等待状态。因此,本质上这与NodeJS异步I/O调用的情况相同。在Node JS中,当调用I/O时,I/O操作将移出当前运行的线程,并发送到事件解复用器以完成和通知。I/O完成后,回调方法将被推送到事件队列进行进一步处理

因此,我看到的唯一区别是,在Node JS中,我们节省了内存(由于每个线程拥有多个调用堆栈)和CPU(由于没有上下文切换而节省)。如果我认为我有足够的内存购买,仅仅因为上下文切换而节省CPU是否会产生巨大的性能差异?

如果我以上的理解不正确,那么java线程和Node JS w.r.t之间的I/O处理有什么不同,以保持CPU繁忙而不浪费CPU周期。我们是否只使用Node JS节省上下文切换CPU周期,或者还有更多

根据回答,我想添加另一个场景:

请求A、请求B同时到达J2ee服务器。在这个多线程环境中,每个请求需要10毫秒才能完成。在10毫秒中,5毫秒用于执行代码逻辑以计算某些逻辑,5毫秒用于从DBMS中提取大型数据集的I/O。对DBMS的调用是代码的最后一行,之后应将响应发送到客户端

如果将同一个应用程序转换为节点JS应用程序,则可能会发生这种情况

  • 请求A出现时,5毫秒用于处理请求

  • DBMS调用是从代码中命中的,但它是非阻塞的 被推送到事件队列

  • 5毫秒后,请求B被送达并再次发送 请求B被推送到事件队列以完成I/O。请求B 处理需要5毫秒
  • 事件循环运行,拾取回调 请求A的处理程序,然后将响应发送给客户端 响应在10毫秒后发送,因为Req A和Req B都需要5分钟 ms用于同步代码块处理
  • 现在,在这种情况下节省的时间在哪里?除了切换上下文和创建两个线程之外。对于节点JS,Req A和Req B都需要10毫秒

    据我所知,在多线程同步环境中,如果I/O 启动时,运行线程被抢占并移回 等待状态。所以本质上这与NodeJS发生的情况相同 异步I/O调用

    不,在NodeJS中,异步I/O调用是一个。这意味着,一旦线程进行了I/O调用,它就不会等待I/O完成,并继续执行下一个语句/任务

    一旦I/O完成,它将从中拾取下一个任务,并最终执行在进行I/O调用时提供给它的回调处理程序

    如果我认为我有足够的记忆力购买,那就节约吧。 CPU由于上下文切换而单独产生了巨大的性能 区别

    除此之外,储蓄也来自这两个方面

    • 不必等待I/O完成
    • 由于线程是有限的,所以不必生成线程,因此系统的容量不受它可以生成多少线程的限制
    除了切换上下文和创建2个线程之外。需求A和需求B 使用Node JS时,两者都花费了10毫秒


    你在这里打折一件事-线程在一个特定的时间间隔后一个接一个地收到两个请求。因此,如果一个线程需要10秒,那么它将需要一个新线程来执行第二个请求。将其扩展到数千个请求,您的操作系统必须生成数千个线程来处理如此多的并发用户。参考这个

    但关键是CPU在多线程环境中并不理想,它会选择另一个准备运行的线程,就像在NodeJS中一样?因此,为了运行代码,CPU得到了最佳利用。这两者之间有什么区别吗?@learnerFromHell的区别来自于-1)更少的上下文切换2)更少的线程使3)更少的等待CPU周期被利用,因为磁盘操作的负担(这些操作占用的CPU较少,但无论如何都可能有很高的时间成本)不是由nodejs应用程序生成的。@learnerFromHell IO通常与CPU无关。因此,在这种情况下,使用多线程最大化CPU潜力是完全没有用的。节点没有上下文切换或具有多个线程。基本上有两种等待IO的方法。阻塞,这意味着执行线程将暂停,直到返回值。或者,您不能阻塞并持续检查缓冲区以查看是否有响应,甚至不能在数据进入时逐段处理它,这就是节点的基本功能。回调并不是唯一的逻辑。只有在完成时才会调用您的回调,但如果您有另一个请求,您可以在同一线程上处理,因为您的线程没有被阻止。@learnerFromHell如果您的应用程序在调用I/O之前要花5毫秒处理每个请求,通过一个线程,您可以每秒获得200个并发请求(否则需要200个不同的线程才能实现)。然而,如果I/O耗时,最终吞吐量将明显降低。显然,您需要权衡这种方法的利弊,并进行相应的设计。Nodejs并不能保证每个场景都有更好的性能,它是为了增加容量而设计的,不一定是为了提高性能