zoukankan      html  css  js  c++  java
  • JavaScript并发模型和事件循环

      1、简介

      JS有一个基于“事件循环”的并发模型。这个模型和其他语言(如C和Java)的模型不太一样。

      下图描述的是一个理论模型,现代JS引擎在此基础上实现和进行了很多优化:

      2、模型详细介绍

      1)相关概念

      (1)栈Stack:如下例,在调用g之前,以及在g返回之后,栈都为空。

    function f(b) { var a = 12; return a + b + 35; }
    function g(x) { var m = 4; return f(m * x); }
    g(21);

      (2)堆:这里不介绍。

      (3)队列:待处理消息的列表,每条消息都关联一个回调函数。

      JavaScript是单线程的(多进程/多线程往往有更大的内存开销、上下文切换开销和数据竞争问题等),这意味着需要有一个队列保存异步执行的代码。

      I、入队操作。例如,某个按钮被按下时,它的事件处理器代码被添加到队列;接收到某个Ajax响应时,回调函数的代码被添加到队列;对于定时器,当指定时间过去后将其回调函数的代码添加到队列。

      II、出队操作。队列中没有任何代码是立刻执行的,但一旦进程空闲(此时栈为空)则尽快执行。进程每次从队列中取出一条消息并调用其回调函数(异步操作的结果通过回调函数获得)。这使得栈变为非空。当栈再次变为空时,表示该消息处理完毕。

      (4)事件循环。得名于它通常的实现方式:

    // 所谓事件循环,就像代码从一个循环中不断取出而运行一样
    while (queue.waitForMessage()) { queue.processNextMessage(); }  // waitForMessage():当前没有消息时执行同步等待

      维基百科的定义:event loop/message dispatcher/message loop/run loop/...是一个程序结构,用于等待和分发(dispatch)事件或消息。

      node.js依赖于libev提供的事件循环。

      2)模型特点:

      (1)完整运行(Run-to-completion):每条消息处理完成后,再处理其他消息。

      进入一个函数后,只有在它完整运行后才会“切换”到其他代码,从而无需担心函数操作的数据被意外修改。

      不足之处在于,如果一条消息处理时间过长,则Web应用程序无法响应用户的交互操作,浏览器将提示"a script is taking too long to run"。一个好的做法是缩短消息处理过程,并尽可能把一条消息“切分”为多条。

      例子:

    setTimeout(function cb() { console.log('5 seconds timeout'); }, 5000);
    setTimeout(function cb() { console.log('9 seconds timeout'); }, 9000);
    setTimeout(function cb() { console.log('7 seconds timeout'); }, 7000);
    setTimeout(function cb() { console.log('3 seconds timeout'); }, 3000);
    
    for(var start = +new Date; +new Date - start <= 10000; ) {}  // “模拟”睡眠

      运行大约10s后,输出:

    3 seconds timeout
    5 seconds timeout
    7 seconds timeout
    9 seconds timeout
    

      (2)从不阻塞(也有例外,如alert或同步XHR,但最好避免使用它们):I/O的处理一般借助于事件和回调函数,因此当应用程序在等待一个IndexedDB查询或一个XHR请求返回时,它仍可以处理其他事情。

      参考资料:

      Concurrency model and Event Loop

      《JavaScript异步编程》

      《JavaScript高级程序设计》

    不断学习中。。。

  • 相关阅读:
    多个网站域名使用同一个IP的设置
    Delphi 文本文件操作
    iframe 元素
    ssis 配置 sqlserver 作业
    关闭占用端口号的进程
    如果你知道要往哪里去,全世界都会给你让路
    不再消极,不再忧虑
    bat 拷贝文件并记录日志
    添加 aspnet 账户到共享文件夹
    截止2013年5月,.net 所有技术路线的一个概括
  • 原文地址:https://www.cnblogs.com/hanerfan/p/5913699.html
Copyright © 2011-2022 走看看