在上一篇博客中,我对jQuery的队列(queue)机制和动画(animate)机制做了一个深入的解析,在animate的实现机制其核心是依靠queue来完成的,其中在jQuery的链式调用部分,之前我非常疑惑为什么animate内部只需要在第一次入队操作后进行一次出队,然后就可以在第一个动画完成后直接使用next()来实现下一个动画出队,这个问题一度让我非常的疑惑,通过接近三个小时的战斗(debugger对源码执行栈反复测试),然后仿然大悟,给自己一个鄙视的眼神,一度对自己的JavaScript底层机制信心满满的,怎么会困在这么愚蠢的问题上呢?

此刻我接收你们的鄙视,如果你不明白我为什么鄙视自己,那我建议你也先鄙视一下自己,因为这是web前端工程师最不应该忘记(或者不懂)的知识点,通常我们在初学JavaScript语言的时候,老师会特别的强调JavaScript是单线程脚本语言,这也是JavaScript相对Java、C#等语言最大的区别和特点。这么说确实是对的,但是别忽略了浏览器内核的存在,浏览器对JavaScript代码的解析执行也确实是单线程模式,但是浏览器内核不只有JavaScript引擎线程,它还有GUI线程、http网络请求线程、定时器触发线程、浏览器事件处理线程。接下来就一一介绍这些线程在浏览器引擎中所分担的工作机制,然后理解它们都是如何在浏览器引擎中相互配合的,再对这种机制下产生的问题逐个剖析。

一、浏览器常驻的线程

  • js引擎线程:解释执行js代码、用户输入、网络请求
  • GUI线程:绘制用户界面、与js主线程互斥
  • http网络请求线程:处理用户的get、post等请求,等返回结果后将回调函数堆入任务队列
  • 定时触发器线程:setTimeout、setInterval等待时间结束后把执行函数堆入任务队列中
  • 浏览器事件处理线程:将click、mouse等交互事件发生后将这些事件放入事件队列中

二、浏览器线程如何协调工作?

  • 图解解浏览器个线程协调工作流程(上图)
  • 通过队列机制理解JS引擎线程执行机制
  • 了解GUI渲染线程与JS引擎线程的关系
  • 理解UI多线程工作机制

1.浏览器UI主线程协调运转图在前面已经给出来了,通过这个图可以看到JS引擎的单线程内部是采用了队列的方式来实现的。关于队列的详细内部机制这里就不多做解析了,不是很了解的可以参考我的另一篇博客:jQuery使用(九):队列及实现原理、基于队列模拟实现animate()

2.GUI渲染线程和JS线程是互斥的关系,所谓互斥就是当JS引擎运行的时候,GUI渲染引擎就不能运行,反之则相反。这两个引擎的互斥关系比较难被察觉,在正常的程序执行过程中,程序的执行速度远远大于我们的视觉感官,但是有一个不正常的时候我们就很容易理解这种互斥关系了,比如当js代码出现了死循环的时候,你会发现点击按钮时按钮的默认变身效果不会出现,其实在点击按钮时的点击事件已经被异步的添加到了事件处理线程,当等到死循环结(相对较长事件的有限循环)束后,按钮就出现一次变色效果,然后事件回调函数被执行,返回结果。

3.我们前面讲到了JS引擎线程执行机制是基于队列,如果理解了队列就很容易理解其他异步线程(定时器处理线程、事件处理线程、网络请求线程),在通过处理后是这样把它们添加到JS线程中来的了。再解释它们的协调关系前,先来了解异步线程都做了什么,定时器线程当然就是然回调函数在指定的等待时间后,通过定时器处理线程添加到JS执行队列中;事件处理线程就很简单,事件处理引擎会时刻监听浏览器的各种事件,一旦被触发就将对应的回调函数添加到JS执行队列中;网络请求线程相对来说会比较复查,它要通过触发网络请求,通过三次网络握手四次网络挥手的过程,拿到网络请求的数据后,再将对应的请求数据交给JS线程。

4.UI多线程的协调工作就是通过异步线程做预处理,当异步线程处理完了以后,再将对应的函数,数据交给JS线程(入队),然后再由js线程做出队操作,一个一个执行。所以这里就会产生很多的相关链的问题。

三、执行栈、任务队列、事件循环

1.什么是执行栈?

  • 栈是先进后出(FILO)的数据结构
  • 执行栈中存放正在执行的任务,每一个任务叫做“帧”
function foo(c){
var a = 1;
bar(20);
console.log(a + c);
}
function bar(d){
var b = 2;
console.log(b + d);
}
foo(50);

先来理解执行栈的执行过程:

创建foo函数执行帧 --> 进入foo执行栈 ---> 创建bar函数执行帧 --> 进入bar执行栈 ---> 打印结果:22 --> bar弹出栈 --->打印结果:51 -->foo弹出栈。

执行栈相当于JS主线程,当执行栈为空时,主线程才会从执行队列中获取任务,这个过程是循环不断的,因为从执行队列中获取任务拿到代码执行就表示JS线程进入执行栈的过程,当前任务执行完JS执行栈又为空了,所以有循环进入执行队列中获取队列的第一个任务,在进入JS线程中执行,这个过程以此反复进行,直到执行队列中的任务被执行完毕。

2.JS执行栈可以说是JS引擎的主线程,任务队列则是其他异步线程的任务合并集,各个异步线程对任务队列执行入队操作,然后由浏览器的事件轮循(Event Loop)做出队操作(添加到JS主线程中执行)。任务队列是FIFO的数据结构。

3.事件轮循(Event Loop)就是JS主线程循环获取执行队列中的任务,并在JS主线程为空的时候会检查执行队列是否有任务需要执行,并且以定时检查的方式对任务队列进行循环检查。

写之前想写一些由UI多线程和JS单线程产生的示例来加以说明,但是这又会涉及到比较多的其他知识点,比如事件的监听、网络请求、定时器等相关的问题特别多,所以这部分到时候在具体的博客中来剖析我觉得更合适,所这篇博客就是一个非常抽象的原理剖析了,如果有不准确的地方还请指出,当然如果有不能理解的地方也可以给我留言。

最后就开篇提到的jQuery动画函数animate的核心机制问题,其本质就是动画函数内部采用了定时器来实现动画,也就是定时器的异步线程,所以当队列中添加第一个队列就可以马上对队列执行出队操作,而动画函数进入异步状态,所以动画函数会往下执行,将后面的所有链式调用的动画函数的动画都添加到队列中,然后动画队列就可以用next()来直接实现下一个动画出队操作了。这是一个非常经典的队列与定时器异步机制的综合应用。

浏览器UI多线程及JavaScript单线程运行机制的理解的更多相关文章

  1. JavaScript的运行机制

    先来看一段代码然后再来详细的说明js的运行机制,下面的一段代码执行顺序是什么 console.log(1); setTimeout(function () { console.log(2); }, 0 ...

  2. 简述JavaScript的运行机制

    想要理解JavaScript的运行机制,需要分别深刻理解以下几个点: · JavaScript的单线程机制 · 任务队列(同步任务和异步任务) · 事件和回调函数 · 定时器 · Event Loop ...

  3. 浅谈javascript的运行机制

    积累一下这几天学的,记录一下: 一.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程 ...

  4. 我对asp.net运行机制的理解

    有一本书叫<asp.net 本质论>,作者名叫冠军.我看了几次,都没有坚持看下来.这次连续看完了前三章,然后参考网上的资料,总结下我对.net运行机制的理解. 先上两张图: 看着这两张图, ...

  5. [转]JavaScript线程运行机制

    从开始接触js时,我们便知道js是单线程的.单线程,异步,同步,互调,阻塞等.在实际写js的时候,我们都会用到ajax,不管是原生的实现,还是借助jQuery等工具库实现,我们都知道,ajax可以实现 ...

  6. 用一个小例子来谈谈javascript的运行机制

    先上例子! <script type="text/javascript"> console.log('博'); setTimeout(function(){ conso ...

  7. setTimeout运行机制简要理解

    经典例子辅助理解setTimeout工作原理 运行结果: 约1秒后输出:1,再过约1秒后输出:2,接着才立即输出:时间流逝了: 2002 毫秒最后输出:时间又流逝了: 2003 毫秒 在现有浏览器环境 ...

  8. 浏览器多进程架构、浏览器内核多线程、js单线程、GUI 渲染线程 与 JavaScript引擎线程互斥 原理

    浏览器是多进程的,有一个主控进程,以及每一个tab页面都会新开一个进程(某些情况下多个tab会合并进程). 出处:http://www.imweb.io/topic/58e3bfa845e5c1346 ...

  9. 浏览器进程/线程模型及JS运行机制

    浏览器是多进程的,有一个主控进程,以及每一个tab页面都会新开一个进程(某些情况下多个tab会合并进程). 进程可能包括主控进程,插件进程,GPU,tab页(浏览器内核)等等. Browser进程:浏 ...

随机推荐

  1. 全民抵制“辱华”品牌秀,D&G神回复:呵呵~ 那不是我!

    ### 补发一下,前写天写的: 就在今天下午,有网友爆出知名品牌 Dolce&Gabbana(杜嘉班纳)的设计师兼创始人Stefano Gabbana在ins上公然发表辱华言论. 下面截图 可 ...

  2. 终于有人把“TCC分布式事务”实现原理讲明白了!

    之前网上看到很多写分布式事务的文章,不过大多都是将分布式事务各种技术方案简单介绍一下.很多朋友看了还是不知道分布式事务到底怎么回事,在项目里到底如何使用. 所以这篇文章,就用大白话+手工绘图,并结合一 ...

  3. PHP(SentCMS)网站 “新手”捉虫记

    我拖着疲惫的身躯,努力打开眼皮在写...... 昨晚弄到12点,我感觉应该弄好了. 故事开头是这样的:我呢朋友有个网站需要开发,我当时没时间就包给外面的公司了,由于外面公司维护费用比较贵. 那么网站维 ...

  4. 随心测试_软测基础_002_<测试工程师_核心技能体系>

    测试工程师核心技能体系构成 测试基础体系:[对象——>方法——>流程].[测试活动类型——>质量] 测试分析体系:[测试对象分析]——>[测试设计(计划.数据.用例.文档)] ...

  5. vagrant之常用操作

    基本操作: 查看版本: vagrant -v 初始化: vagrant init 启动虚拟机: vagrant up 关闭虚拟机: vagrant halt 重启虚拟机: vagrant reload ...

  6. tomcat 启动窗口乱码

    在tomcat主目录下的conf文件夹里,找到logging.properties文件: 用记事本打开,找到以下内容 java.util.logging.ConsoleHandler.encoding ...

  7. swiper 轮播图,拖动之后继续轮播

    在此贴出swiper官网地址:https://www.swiper.com.cn/api/index.html 示例如下(官网示例): <script> var mySwiper = ne ...

  8. JDK环境配置(Windows)

    JDK环境配置(Windows): 1.下载jdk版本: https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads ...

  9. Python面试知识点小结

    一.Python基础 1.Python语言特性: 动态型(运行期确定类型,静态型是编译型确定类型),强类型(不发生隐式转换,弱类型,如PHP,JavaScript就会发生隐患式转换) 2.Python ...

  10. mysql 导入出csv

    load data infile '/var/lib/mysql-files/ip_address.csv' into table ip_address fields terminated by ', ...