1. 进程与线程
- 进程是资源分配的最小单位,线程是操作系统可识别的最小执行和调度单位
- 一个进程可以有多个线程,线程运行在进程中,一个线程只能属于一个进程,
1.1 本质
- 进程拥有独立的堆栈空间和数据段,开销大,但进程间相互独立,安全性高,且一个崩溃不影响其他。
- 线程拥有独立的堆栈空间,但共享数据段,开销小,切换速度快,效率高,但因为线程是在进程间行进,一个线程崩溃则整个进程崩溃。
1.2 通信
- 因为进程间相互独立,所以通信机制也相对复杂;
- 多个线程运行在同一个进程中,通信更便利;
1.3 适用
- 频繁创建销毁、频繁切换的使用线程;
- 多机分布用进程,多核分布用线程;
2.浏览器是多进程的
浏览器多进程避免了一个页面或一个插件崩溃导致整个浏览器崩溃,提升了用户体验,但也加大了系统资源消耗。
以下列举浏览器中的主要进程:
- Browser 进程:主进程,只有一个,负责浏览器界面显示、用户交互,各页面管理,其他进程的创建、销毁,网络资源管理;
- 第三方插件进程:通常一个插件对应一个进程;
- GPU 进程:用于 3d 绘制,最多一个;
- 浏览器渲染进程(Renderer 进程):通常一个tab页一个(但有时会将多个合并),用于进行页面渲染、脚本执行、事件处理等。
浏览器有多个进程,其中前端的主要操作是在渲染进程中进行的,而渲染进程是多线程的。
2.1 渲染进程是多线程的
以下列举些渲染进程中的常驻线程:
- GUI 渲染线程:解析html、css文件,渲染页面,处理重绘、重排;
- JS 引擎线程:处理 javascript 脚本(注: GUI 渲染线程和 JS 引擎线程是互斥的,JS 引擎线程执行时 GUI 线程会被挂起,因此 JS 执行时间过长可能会造成页面渲染阻塞);
- 事件触发线程:维护一个事件队列,当一个事件被触发时,将其添加到事件队列尾部,等到 JS 引擎空闲时才会来进行处理;
- 定时器线程:setInterval、setTimeout 所在线程,因为 JS 引擎可能会存在阻塞影响计时准确性,所以计时由单独线程控制,计时完毕后添加到事件队列尾,等待 JS 引擎来处理;
- 异步请求线程:建立一个异步请求会新开一个线程,检测到状态变更且设置有回调函数时,会把这个回调添加到事件队列尾,等待 JS 引擎来处理。
2.2 浏览器从输入 url 到页面展示的过程
- DNS 域名解析:通过 DNS 服务器查找,将输入的域名解析为 ip 地址;
- TCP 连接(三次握手):拿到 ip 地址后,TCP 协议会像远端服务器发起连接请求,称为三次握手:
- 源端:可以连接吗?
- 远端:可以,确定吗?
- 源端:确定,连接吧!
- 发送HTTP请求,接受HTTP响应:
- HTTP请求报文格式:请求行+请求头+空行+消息体
- HTTP响应报文格式:状态行+响应头+空行+消息体
- 断开TCP连接( 四次挥手):
- 源端)断开吧?
- 远端)好,我稍微检查一下
- 远端)可以了,断开吧,再见
- 源端)好的,再见
- 浏览器渲染:(渲染的过程逐步完成,不会等到全部解析完才显示)
- 解析 html 构建 dom 树
- 解析 css,构建 cssom 树,结合 dom 树,构建 render 树
- 布局,计算各元素尺寸、位置
- 通过显卡,将内容绘制在屏幕上
参考:
http://www.dailichun.com/2018/01/21/js_singlethread_eventloop.html
https://www.cnblogs.com/quanshubli/p/8552626.html
https://blog.csdn.net/didudidudu/article/details/80181505