什么是Event Loop

Event Loop 是一个很重要的概念,指的是计算机系统的一种运行机制。html

JavaScript语言就采用这种机制,来解决单线程运行带来的一些问题。node

Event Loop

本文参考C. Aaron Cois的《Understanding The Node.js Event Loop》,解释什么是Event Loop,以及它与JavaScript语言的单线程模型有何关系。浏览器

想要理解Event Loop,就要从程序的运行模式讲起。运行之后的程序叫作"进程"(process),通常状况下,一个进程一次只能执行一个任务。多线程

若是有不少任务须要执行,不外乎三种解决方法。异步

(1)排队。由于一个进程一次只能执行一个任务,只好等前面的任务执行完了,再执行后面的任务。async

(2)新建进程。使用fork命令,为每一个任务新建一个进程。函数

(3)新建线程。由于进程太耗费资源,因此现在的程序每每容许一个进程包含多个线程,由线程去完成任务。(进程和线程的详细解释,请看这里。)oop

以JavaScript语言为例,它是一种单线程语言,全部任务都在一个线程上完成,即采用上面的第一种方法。一旦遇到大量任务或者遇到一个耗时的任务,网页就会出现"假死",由于JavaScript停不下来,也就没法响应用户的行为。spa

你也许会问,JavaScript为何是单线程,难道不能实现为多线程吗?线程

这跟历史有关系。JavaScript从诞生起就是单线程。缘由大概是不想让浏览器变得太复杂,由于多线程须要共享资源、且有可能修改彼此的运行结果,对于一种网页脚本语言来讲,这就太复杂了。后来就约定俗成,JavaScript为一种单线程语言。(Worker API能够实现多线程,可是JavaScript自己始终是单线程的。)

若是某个任务很耗时,好比涉及不少I/O(输入/输出)操做,那么线程的运行大概是下面的样子。

synchronous mode

上图的绿色部分是程序的运行时间,红色部分是等待时间。能够看到,因为I/O操做很慢,因此这个线程的大部分运行时间都在空等I/O操做的返回结果。这种运行方式称为"同步模式"(synchronous I/O)或"堵塞模式"(blocking I/O)。

若是采用多线程,同时运行多个任务,那极可能就是下面这样。

synchronous mode

上图代表,多线程不只占用多倍的系统资源,也闲置多倍的资源,这显然不合理。

Event Loop就是为了解决这个问题而提出的。Wikipedia这样定义:

"Event Loop是一个程序结构,用于等待和发送消息和事件。(a programming construct that waits for and dispatches events or messages in a program.)"

简单说,就是在程序中设置两个线程:一个负责程序自己的运行,称为"主线程";另外一个负责主线程与其余进程(主要是各类I/O操做)的通讯,被称为"Event Loop线程"(能够译为"消息线程")。

asynchronous mode

上图主线程的绿色部分,仍是表示运行时间,而橙色部分表示空闲时间。每当遇到I/O的时候,主线程就让Event Loop线程去通知相应的I/O程序,而后接着日后运行,因此不存在红色的等待时间。等到I/O程序完成操做,Event Loop线程再把结果返回主线程。主线程就调用事先设定的回调函数,完成整个任务。

能够看到,因为多出了橙色的空闲时间,因此主线程得以运行更多的任务,这就提升了效率。这种运行方式称为"异步模式"(asynchronous I/O)或"非堵塞模式"(non-blocking mode)。

这正是JavaScript语言的运行方式。单线程模型虽然对JavaScript构成了很大的限制,但也所以使它具有了其余语言不具有的优点。若是部署得好,JavaScript程序是不会出现堵塞的,这就是为何node.js平台能够用不多的资源,应付大流量访问的缘由。

(完)