js 进程和线程(高阶)
2022-07-18 本文已影响0人
前端末晨曦吖
点击打开视频讲解:https://www.bilibili.com/video/BV1Ea411D7VR/?vd_source=66e2692cc471862d6c3f85dc4b9ea5dd
进程和线程 概念
进程:程序的一次执行,它占有一片独有的内存空间
线程:是进程内的一个独立执行单元,是程序执行的一个完整流程,是CPU的最小的调度单元
单线程和多线程 概念
单线程:一个进程内有一个线程
多线程:一个进程内有多个线程
关于进程的相关知识
应用程序必须运行在某个进程的某个线程上
一个进程中至少有一个运行的线程:主线程,进程启动后自动创建
一个进程中也可以同时运行多个线程,即程序是多线程运行的
一个进程内的数据可以供其中的多个线程直接共享
多个进程之间的数据是不能直接共享的
线程池:保存多个线程对象的容器,实现线程对象的反复利用
线程和进程的优缺点
多线程的优点:(1)有效提升CPU的利用率;
多线程的缺点:(1)创建多线程开销;(2)线程间切换开销;(3)死锁与状态同步
单线程优点:顺序编程简单易懂 (js单线程运行 )
多线程缺点:效率低 (h5中Web Workers可以多线程运行)
浏览器运行是单线程还是多线程?
浏览器运行是多进程还是但进程? 有的是单进程(火狐 IE)多进程(chrome 新版IE)
定时器的回调函数是在分线程执行的吗?
在主线程执行的 js是单线程执行的
浏览器进程
浏览器作为一个计算机应用程序,如果打开浏览器默认进入一个空白页,相当于新起了一个浏览器的
主进程和GPU进程,如果再打开一个标签页,则又创建了一个渲染进程。
调出chrome的任务管理器(shift+esc或在标签栏空白处点右键),可以看到:
201904251257364.jpg
- 浏览器是多进程的
- 浏览器之所以能够运行,是因为系统给它的进程分配了资源(cpu、内存)
- 浏览器每打开一个Tab页,就相当于创建了一个独立的浏览器进程。
浏览器多进程的优点
避免单个页面崩溃影响整个浏览器
避免第三方插件崩溃影响整个浏览器
多进程充分利用多核优势
方便使用沙盒模型隔离插件等进程,提高浏览器安全性
简单的说,浏览器多进程避免了一个页面或一个插件的崩溃导致整个浏览器的崩溃,
大大改善了用户体验。
PS:“沙盒”技术的实践运用流程是:让疑似病毒文件的可疑行为在虚拟的“沙盒”里充分表演,“沙盒”会记下它的每一个动作;当疑似病毒充分暴露了其病毒属性后,“沙盒”就会执行“回滚”机制:将病毒的痕迹和动作抹去,恢复系统到正常状态。如果您还不懂,那说的再简单一些。想象一下,在一个装满了平整细沙的盒子里,我们可以尽情随意地在上面作画、涂写,无论画的好坏,最后轻轻一抹,沙盒又回到了原来的平整状态。沙盒的魅力就在于他允许你出错,还可以给你改正的机会。
浏览器多进程的缺点
浏览器多进程提高用户体验的同时是要付出代价的,那就是对系统资源的消耗加大,特别是内存
的消耗。
浏览器有哪些进程
Browser进程
浏览器的主进程(负责协调、主控),只有一个,相当于浏览器的大脑,作用有:
负责浏览器界面显示,与用户交互,如前进,后退等;
负责各个页面的管理,创建和销毁其他进程;
将渲染线程得到的内存中的位图渲染到用户界面上;
网络资源的管理,下载等。
第三方插件进程
每种类型的插件对应一个进程,仅当使用该插件时才创建。
GPU进程
最多一个,负责3D绘制,只有当该页面使用了硬件加速才会使用它,来渲染页面。否则的话,
不使用这个进程,而是用Browser进程来渲染页面。
浏览器渲染进程(Renderer进程)
也称浏览器内核、Renderer进程(内部是多线程的),默认每个Tab页面一个进程,互不影响。主要作用为页面渲染,脚本执行,事件处理,任务队列轮询等。
浏览器有时会将多个渲染进程合并(譬如打开多个空白标签页后,会发现多个空白标签页被合并成了一个进程)。
222.jpg
前端重点:渲染进程(浏览器内核)
现在我们再来捋一下进程和线程,浏览器是多进程的,每打开一个tab页相当于创建了一个渲染进程,
每个渲染进程是又多线程的。
页面的渲染,JS的执行,事件的循环,都在渲染进程中进行。
渲染进程中的主要常驻线程
GUI渲染线程
负责渲染浏览器界面,解析HTML,CSS,构建DOM树和RenderObject树,布局和绘制等。
当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行。
JS引擎线程
也称为JS内核,负责处理Javascript脚本程序。(例如V8引擎)
JS引擎线程负责解析Javascript脚本,运行代码。
JS引擎一直等待着任务队列中任务的到来,然后加以处理,浏览器无论什么时候都只有一个JS线程
在运行JS程序,JS是单线程的。
PS:GUI渲染线程与JS引擎线程是互斥的,当JS引擎执行时GUI线程会被挂起,GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行;如果JS执行的时间过长,会导致页面渲染被阻塞。
事件触发线程
接受浏览器里面的操作事件响应。如在监听到鼠标、键盘等事件的时候, 如果有事件处理函数,就将对应的任务压入任务队列(添加到待处理队列的队尾),等待JS引擎的处理。
事件触发线程管理着一个任务队列。
定时触发器线程
setInternal与setTimeout所在线程
浏览器定时计数器并不是由JavaScript引擎计数的,(因为JavaScript引擎是单线程的, 如果处于
阻塞线程状态就会影响记计时的准确)
因此通过单独线程来计时并触发定时(计时完毕后,添加到事件队列中,等待JS引擎空闲后执行)
注意,W3C在HTML标准中规定,规定要求setTimeout中低于4ms的时间间隔算为4ms。
异步http请求线程
在XMLHttpRequest在连接后是通过浏览器新开一个线程请求
将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件
队列中。再由JavaScript引擎执行。
Browser进程和渲染进程的通信过程
就像前文中那样新打开谷歌浏览器,并打开任务管理器,可以看到:任务管理器中出现了三个进程,来了解一下浏览器的主进程和渲染进程是怎样通信的:
Browser进程收到用户请求(输入网址并回车),首先需要获取页面内容(譬如通过网络下载资源),
随后将该任务通过RendererHost接口传递给Render进程。
Renderer进程的Renderer接口收到消息,简单解释后,交给渲染线程,然后开始渲染。
渲染线程接收请求,加载网页并渲染网页,这其中可能需要Browser进程获取资源和需要GPU
进程来帮助渲染;
可能会有JS线程操作DOM(这样可能会造成回流并重绘);
最后Render进程将结果传递给Browser进程;
Browser进程接收到结果并将结果绘制出来