zoukankan      html  css  js  c++  java
  • 初探nodejs事件循环机制event loop

    nodejs的特点

    nodejs 具有事件驱动和非阻塞I/O的特点。

    事件驱动是指nodejs把每一个任务当成事件来处理。

    非阻塞I/O是nodejs遇到I/O任务时,会从线程池调度单独的线程处理I/O操作,不会阻塞主线程。

    事件循环原理

    Node.js 在主线程里维护了一个事件队列,当接到请求后,就将该请求作为一个事件放入这个队列中,然后继续接收其他请求。

    当主线程空闲时(没有请求接入时),就开始循环事件队列,检查队列中是否有要处理的事件,这时要分两种情况:

      如果是非 I/O 任务,就亲自处理,并通过回调函数返回到上层调用;

      如果是 I/O 任务,就从 线程池 中拿出一个线程来处理这个事件,并指定回调函数,然后继续循环队列中的其他事件。

    当线程中的 I/O 任务完成以后,就执行指定的回调函数,并把这个完成的事件放到事件队列的尾部,等待事件循环,当主线程再次循环到该事件时,就直接处理并返回给上层调用。

    流程图

    每次循环的六个阶段

      timers阶段:这个阶段执行定时器队列中的回调,如 setTimeout() 和 setInterval()

      I/O callbacks: 这个阶段执行几乎所有的回调。但是不包括close事件,定时器和setImmediate()的回调。

      idle, prepare: 这个阶段仅在内部使用,可以不必理会。

      poll: 等待新的I/O事件,node在一些特殊情况下会阻塞在这里。

      check: setImmediate()的回调会在这个阶段执行。

      close callbacks: 例如socket.on('close', ...)这种close事件的回调。

    下面我们来按照代码第一次进入libuv引擎后的顺序来详细解说这些阶段:

      当个v8引擎将js代码解析后传入libuv引擎后,循环首先进入poll阶段。

      poll阶段的执行逻辑如下:

        先查看poll queue中是否有事件,有事件就按先进先出的顺序依次执行回调。

        当queue为空时,会检查是否有setImmediate()的callback,如果有就进入check阶段执行这些callback。

        当queue为空时,同时也会检查是否有到期的timer,如果有,就把这些到期的timer的callback按照调用顺序放到timer queue中,之后循环会进入timer阶段执行queue中的 callback。

        这两者的顺序是不固定的,收到代码运行的环境的影响。

        如果两者的queue都是空的,那么loop会在poll阶段停留,直到有一个i/o事件返回,循环会进入i/o callback阶段并立即执行这个事件的callback。

        值得注意的是,poll阶段在执行poll queue中的回调时实际上不会无限的执行下去。

        有两种情况poll阶段会终止执行poll queue中的下一个回调:1.所有回调执行完毕。2.执行数超过了node的限制。

    特别感谢:

    https://www.cnblogs.com/onepixel/p/7143769.html

     

  • 相关阅读:
    java错误分析之junit测试错误(实验一)
    oracle逐步学习总结之oracle分页查询(基础三)
    OracleServer总结进阶之系统分析(进阶完结)
    QMS 的趨勢概述
    Python 類別 class 的繼承 Inheritance
    Python 面向導向語言 Object Oriented Programming Language
    Python 參考資源
    Dynamics 365-CRM又报看不懂的错误了
    Dynamics 365-为什么查到的Record的Id是Guid初始值
    Dynamics 365-如何下载新版本的Tools
  • 原文地址:https://www.cnblogs.com/zifayin/p/11419808.html
Copyright © 2011-2022 走看看