作者:NastassiaOvchinnikova是一个免费的跨平台JavaScript运行环境,虽然它本质上是单线程的,但可以在后台使用多线程来执行异步代码。由于Node.js的非阻塞特性,不同的线程执行不同的回调,这些回调首先委托给事件循环。Node.js运行时会处理所有这些。为什么要使用NodeJS?JavaScript最初是作为一种单线程编程语言构建的,仅在Web浏览器中运行。这意味着在一个进程中,在给定时间只能执行一组指令。只有在当前代码块执行完成后才移动到下一个代码块。然而,JavaScript的单线程特性使得实现起来很容易。最初,JavaScript仅用于向网站添加少量交互性。所以不需要多线程。但时代变了,用户的要求越来越高,JavaScript已经成为“Web上最流行的编程语言”。多线程现在很普遍。由于JavaScript是一种单线程语言,因此无法在其中实现多线程。幸运的是,在这种情况下,有一个很好的解决方法:Node.js。由于JavaScript运行时环境(尤其是JavaScript)的普遍流行,Node.js框架并不缺乏。在继续这篇文章之前,我们先了解一下Node.js的几个要点:可以使用send函数将消息从子进程传递给其他子进程,主进程支持fork多进程fork进程?在两种情况下我们需要fork一个进程:通过将任务委派给其他进程以释放内存来提高速度,以及为了卸载单个进程可以将数据发送到子进程并将其发回。Node.js方式Node.js使用两种类型的线程:主线程由事件循环处理,工作池中有很多工作线程。事件循环负责获取回调或函数并注册它们以供将来执行。它与正确的JavaScript代码在同一个线程中运行。一旦JavaScript操作阻塞了线程,事件循环也会被阻塞。工作池是负责生成和处理不同线程的执行模型。它同步执行任务,然后将结果返回给事件循环,最后事件循环将结果提供给回调。总而言之,workerpool负责异步I/O操作,即与系统磁盘和网络的交互。fs和crypto等模块是使用工作池的主要模块。由于工作池是在libuv库中实现的,因此JS和C++之间的Node.js内部通信存在轻微延迟。但这几乎是不可察觉的。一切都很好,直到我们遇到了同步执行复杂操作的需求。任何需要大量时间执行的函数都会导致主线程阻塞。如果程序有很多CPU密集型函数,会导致服务器吞吐量明显下降。在最坏的情况下,服务器将变得无响应并且无法将任务委托给工作池。AI、大数据和机器学习等领域无法从Node.js中受益,因为这些操作会阻塞主线程并导致服务器无响应。但随着Node.jsv10.5.0的到来,这种情况发生了变化,它增加了对多线程的支持。并发性和CPU绑定任务的挑战在JavaScript中建立并发性可能很困难。允许多个线程访问同一内存会产生竞争条件,这不仅使错误难以重现,而且也难以解决。Node.js最初是作为基于异步I/O的服务器端平台实现的。通过简单地消除对线程的需要,这使很多事情变得更容易。是的,Node.js程序是单线程的,但不是典型的方式。我们可以在Node.js中并行运行,但不需要创建线程。操作系统和虚拟机协同工作,并行使用I/O,然后当需要将数据传回给JavaScript代码时,JS代码在单线程中运行。除JS代码外,所有内容都在Node.js中并行运行。与异步块不同,JS的同步块总是一次执行一个。在JS中等待I/O事件发生比代码执行花费的时间要多得多。Node.js程序只调用所需的函数或回调,而不会阻塞其他代码的执行。最初,JavaScript和Node.js都不是为了处理CPU密集型或CPU密集型任务。当代码最少时,执行会很敏捷。但是计算越大,执行越慢。如果您仍然尝试在JS和Node中执行CPU密集型任务,它将冻结浏览器中的UI并将所有I/O事件排队。尽管如此,我们已经走了很长一段路。现在我们有了worker_threads模块。worker_threads模块让多线程变得简单Node.jsv10.5.0于2018年6月发布,引入了worker_threads模块。它促进了流行的JavaScript运行时环境中的并发性。该模块允许创建功能齐全的多线程Node.js应用程序。从技术上讲,工作线程是在单独的线程中生成的一些代码。要开始使用工作线程,您需要首先导入worker_threads模块。之后需要创建Worker类的实例来创建工作线程。创建Worker类的实例时,有两个参数:第一个参数提供扩展名为.js或.mjs的文件的路径,其中包含工作线程的代码,第二个参数提供一个对象,其中包含属性包含工作线程开始执行时将访问的数据。工作线程能够分派多个消息事件。因此,回调方法优先于返回承诺。工作线程之间的通信是基于事件的,即侦听器设置为在工作线程发送事件后立即调用。4个最常见的事件是:worker.on('error',(error)=>{});当工作线程中存在未捕获的异常时发出。接下来工作线程终止,错误作为回调中的第一个参数可用。worker.on('exit',(exitCode)=>{})当工作线程退出时触发。如果在工作线程中调用了process.exit(),exitCode将提供给回调。如果worker.terminate()终止工作线程,则代码为1。worker.on('消息',(data)=>{});当工作线程向父线程发送数据时发出。worker.on('在线',()=>{});当工作线程停止解析JS代码并开始执行它时发出。虽然不常用,但在线事件在某些情况下可能会提供更多信息。使用工作线程的方法有两种使用工作线程的方法:方法1-涉及生成工作线程、执行其代码并将结果发送到父线程。此方法需要每次为新任务从头创建一个新的工作线程。方法2-涉及生成工作线程和设置消息事件的侦听器。每次触发消息时,工作线程都会执行代码并将结果发送回父线程。工作线程保持活动状态以备将来使用。方法2也称为workerpooling。这是因为该方法涉及创建一个工作池,让他们先等待,并在需要时分派消息事件以执行任务。由于从头开始创建worker需要创建虚拟机并解析和执行代码,Node.js官方文档推荐方法二。而且方法二比方法一更实用、更高效。worker_threads模块中的重要属性是MainThread——当不在工作线程内操作时,此属性为真。如果需要,可以在工作文件的开头包含一个简单的if语句。这确保它仅作为工作线程运行。parentPort–用于与父线程通信的MessagePort实例。threadId–分配给工作线程的唯一标识符。workerData–要包含在工作线程的构造函数中的数据。Node.js中的多进程为了使Node.js能够利用多核系统的功能,可以使用多个进程。流行的javascript运行时环境有一个名为cluster的模块,它提供对多处理的支持。使用cluster模块生成多个可以共享公共端口的子进程。当子进程发挥作用时,使用NodeJS的系统可以处理更大的工作负载。Node.js物联网后端已成为全球数百万公司的首选平台。因此,企业要充分发挥潜力并在此过程中脱颖而出,就必须拥有强大的在线形象。这一切都始于一个强大而直观的网站。要创建一个完美的网站,选择最好的前端和后端技术很重要。尽管本质上是单线程的,但Node.js是开发后端Web服务的首选。尽管有大量的后端多线程选项,但知名公司更喜欢Node.js。这是因为Node.js提供了在JavaScript中使用多线程的变通方法,JavaScript已经是“网络上最流行的编程语言”。总结worker_threads模块提供了一种在Node.js程序中实现多线程的简单方法。通过将繁重的计算委托给工作线程,您可以显着提高服务器的吞吐量。由于支持多线程,Node.js将继续吸引越来越多来自人工智能、大数据和机器学习等计算密集型领域的开发人员、工程师和其他专业人士。
