任务队列/事件队列

  "任务队列"是一个事件的队列,IO设备完成一项任务,就在"任务队列"中添加一个事件,表示相关的异步任务可以进入"执行栈"了。主线程读取"任务队列",就是读取里面有哪些事件。

  "任务队列"中的事件,除了IO设备的事件以外,还包括一些用户产生的事件(比如鼠标点击、页面滚动等等)。只要指定过回调函数,这些事件发生时就会进入"任务队列",等待主线程读取。

  所谓"回调函数"(callback),就是那些会被主线程挂起来的代码。异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行对应的回调函数。

  "任务队列"是一个先进先出的数据结构,排在前面的事件,优先被主线程读取。主线程的读取过程基本上是自动的,只要执行栈一清空,"任务队列"上第一位的事件就自动进入主线程。

异步执行

  JavaScript语言的一大特点就是单线程,单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。如果排队是因为计算量大,CPU忙不过来,倒也算了,但是很多时候CPU是闲着的,因为IO设备(输入输出设备)很慢(比如Ajax操作从网络读取数据),不得不等着结果出来,再往下执行。

  JavaScript语言的设计者意识到,这时主线程完全可以不管IO设备,挂起处于等待中的任务,先运行排在后面的任务。等到IO设备返回了结果,再回过头,把挂起的任务继续执行下去。于是,所有任务可以分成两种:

  • 一种是同步任务(synchronous):指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务
  • 一种是异步任务(asynchronous):指的是,不进入主线程、而进入"任务队列"的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

异步执行的过程如下:

(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。

(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。

(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。

(4)主线程不断重复上面的第三步。

Node.js的事件轮询Event Loop

  在Node.js底层有一个线程池,线程池专门用来执行各种堵塞操作,这样不会影响单线程这个主线程进行队列中事件轮询和一些任务执行,线程池操作完以后,又会作为事件生产者将操作结果放入同一个队列中。

一个事件轮询Event Loop需要三个组件:

  1. 事件队列Event Queue,属于FIFO模型,一端推入事件数据,另外一端拉出事件数据,两端只通过这个队列通讯,属于一种异步的松耦合。
  2. 队列的读取轮询线程,事件的消费者,Event Loop的主角。
  3. 单独线程池Thread Pool,专门用来执行长任务,重任务,干繁重体力活的。

  在Node.js中,因为只有一个单线程不断地轮回查询队列中是否有事件,对于数据库 文件系统等I/O操作,包括HTTP请求等等这些容易堵塞等待的操作,如果也是在这个单线程中实现,肯定会堵塞影响其他工作任务的执行,Javascript/Node.js会委托给底层的线程池执行,并会告诉线程池一个回调函数,这样单线程继续执行其他事情,当这些堵塞操作完成后,其结果与提供的回调函数一起再放入队列中当单线程从队列中不断读取事件,读取到这些堵塞的操作结果后,会将这些操作结果作为回调函数的输入参数,然后激活运行回调函数。

  请注意,Node.js的这个单线程不只是负责读取队列事件,还会执行运行回调函数,这是它区别于多线程模式的一个主要特点,多线程模式下,单线程只负责读取队列事件,不再做其他事情,会委托其他线程做其他事情(特别是多核的情况下,一个CPU核负责读取队列事件,一个CPU核负责执行激活的任务,这种方式最适合很耗费CPU计算的任务),反过来,Node.js的执行激活任务也就是回调函数中的任务还是在负责轮询的单线程中执行,这就注定了它不能执行CPU繁重的任务,比如JSON转换为其他数据格式等等,这些任务会影响事件轮询的效率。

node.js中的事件轮询Event Loop的更多相关文章

  1. js中的事件轮询(event loop)机制

    异步任务指的是,不进入主线程.而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行. ...

  2. Node.js的事件轮询Event Loop原理

    Node.js的事件轮询Event Loop原理解释 事件轮询主要是针对事件队列进行轮询,事件生产者将事件排队放入队列中,队列另外一端有一个线程称为事件消费者会不断查询队列中是否有事件,如果有事件,就 ...

  3. 对Node.JS的事件轮询(Event Loop)的理解

    title: Node.JS的事件轮询(event loop)的理解 categories: 理解 tags: Node JS 机制 当我们知道I/O操作和创建新线程的开销是巨大的! 网站延迟的开销 ...

  4. 事件轮询 event loop

    Understanding the node.js event loop The first basic thesis of node.js is that I/O is expensive: So ...

  5. 理解JavaScript中的事件轮询

    原文:http://www.ruanyifeng.com/blog/2014/10/event-loop.html 为什么JavaScript是单线程 JavaScript语言的一大特点就是单线程,也 ...

  6. 【nodejs原理&源码赏析(7)】【译】Node.js中的事件循环,定时器和process.nextTick

    [摘要] 官网博文翻译,nodejs中的定时器 示例代码托管在:http://www.github.com/dashnowords/blogs 原文地址:https://nodejs.org/en/d ...

  7. 【nodejs原理&源码赏析(7)】【译】Node.js中的事件循环,定时器和process.nextTick

    目录 Event Loop 是什么? Event Loop 基本解释 事件循环阶段概览 事件循环细节 timers pending callbacks poll阶段 check close callb ...

  8. 初步揭秘node.js中的事件

    当你学习node.js的时候,Events是一个非常重要的需要理解的事情.非常多的Node对象触发事件,你能在文档API中找到很多例子.但是关于如何写自己的事件和监听,你可能还不太清楚.如果你不了解, ...

  9. node.js koa 实现长轮询

    长轮询的实现原理:浏览器发出请求之后,服务端资源如果没有就绪,那么并不立即返回,而是在一个时间范围内,不断地去查询资源是否就绪,如果就绪,就返回资源,如果超时了还没有就绪,就返回超时. 代码实现如下: ...

随机推荐

  1. js 设计模式:观察者和发布订阅模式

    总是把这两个当作同一个模式,但其实是不太一样的,现在重温一下. 观察者模式 观察者直接订阅目标,当目标触发事件时,通知观察者进行更新 简单实现 class Observer { constructor ...

  2. STM32F103之I2C学习记录

    26.3.1  模式选择 该外设可以在以下四种模式之一 1)从机发送模式 2)从机接收模式 3)主机发送模式 4)主机接收模式 IIC协议时序 MSB:Most Significant Bit(最高有 ...

  3. spring框架相关概念

    软件行业的二八法则?技术中只有20%是最常用和最关键的,决定你的基础,后面的80%决定你的潜能! 概念: 1,轻量级框架,用户需要什么功能就自己添加相应的功能模块,不像重量级框架,一旦用,所有功能都添 ...

  4. 吴裕雄 人工智能 java、javascript、HTML5、python、oracle ——智能医疗系统WEB端智能分诊代码简洁版实现

    <%-- Document : getInfo Created on : 2018-10-7, 21:36:37 Author : acer --%> <%@page import= ...

  5. Android日常debug

    获取SD卡文件 File file=new File(Environment.getExternalStorageDirectory().toString()+"/Music", ...

  6. [1/100]Python安装

    Python官方版本下载地址: https://www.python.org/downloads/release (上图为3.8.2网络安装版) 默认安装: pip Python安装模块 tkinte ...

  7. 启动ubuntu就直接进入GRUB2.02的命令行界面的问题

    问题:启动ubuntu就直接进入GRUB2.02的命令行界面原因:grub2引导出现问题. 解决方法:图形方法,引导修复 (1)电脑上插入Ubuntu系统启动引导U盘(如果没有引导U盘,就到官网下载一 ...

  8. layui 延时加载

    //延时关闭当前页面,并刷新父页面layer.msg('提交成功',{time: 1800},function () { parent.layer.close(index); window.paren ...

  9. 2.1.FastDFS-单机拆分版-单机版安装配置

    Centos610系列配置 1.什么是FastDFS? FastDFS是一个开源的分布式文件系统,她对文件进行管理,功能包括:文件存储.文件同步.文件访问(文件上传.文件下载)等,解决了大容量存储和负 ...

  10. oracle用户表字段注释

    SELECT C.TABLE_NAME,NUM_ROWS,(select COMMENTS from user_tab_comments WHERE TABLE_NAME=C.TABLE_NAME) ...