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

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

loop示例

要想理解Event Loop,就要从程序运行的模式讲起。运行以后的程序叫"进程"(process),一般情况下,一个进程一次只能执行一个任务。

如果有很多个任务需要执行,不外乎三种解决办法

1
2
3
4
(1)、排队。因为一个进程一次只能执行一个任务,只好等前面任务
(2)、新建进程。使用fork命令,为每个任务新建一个进程。
(3)、新建线程。因为进程太耗费资源,所以如今的程序往往允许一个进程包含多个线程,由线程去完成任务。

进程与线程相关知识

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

为什么javascript是单线程呢?难道不能实现为多线程么?

这跟历史有关系,jsvascript从诞生起就是单线程,原因大概是不想让浏览器变的太复杂,因为多线程需要共享资源、且有可能修改彼此的运行结果,对于一种脚本语言来说,这就太复杂了,后来就约定俗成,javascript是一种单线程语言(Worker API 可以实现多线程, 但javascript本身是单线程的)。

如果某个任务很耗时,比如高(I/O 输入输出操作),那么线程的运行如下: IO示例

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

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

多线程示例

1
2
3
4
> 大概简介:
> CPU -> 单个CPU一次只能运行一个任务
> 进程好比车间,CPU所处理的单个任务;任一时刻,CPU处理一个进程
> 一个车间有很多工人协同,线程好比车间工人,一个进程可以有多个线程,进程内享有空间共享。

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

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

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

简单来说,就是程序中设置两个线程:一个负责程序本身的运行,称为"主线程"; 另一个负责主线程与其他进程(主要是各种 I/O操作)的通信,被称为"Event Loop线程"(可以译为"消息线程")。

Event Loop

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

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

这正是javascript语言的运行方式。单线程模型虽然对Javascript构成了很大的限制,但也因此使它具备了其他语言不具备的优势。如果部署的好,Javascript程序是不会出现堵塞的,这就是为什么node.js平台可以用很少的资源,应付大流量访问的原因。

转载自 http://www.ruanyifeng.com/blog/2013/10/event_loop.html