大家很早就知道JS是一门单线程的语言。但是也时不时的会看到进程这个词。首先简单区分下线程和进程的概念
1. 简单理解进程
- 进程是一个工厂,工厂有它的独立资源
- 工厂之间相互独立
- 线程是工厂中的工人,多个工人协作完成任务
- 工厂内有一个或多个工人
- 工人之间共享空间
2. 简单理解线程
- 工厂的资源 -> 系统分配的内存(独立的一块内存)
- 工厂之间的相互独立 -> 进程之间相互独立
- 多个工人协作完成任务 -> 多个线程在进程中协作完成任务
- 工厂内有一个或多个工人 -> 一个进程由一个或多个线程组成
- 工人之间共享空间 -> 同一进程下的各个线程之间共享程序的内存空间(包括代码段、数据集、堆等)
3. 浏览器是多进程的
上面的1.1和1.2可能还是有些抽象。接下来用与前端息息相关的浏览器为例展开。
当你打开浏览器开了好几个网页的时候,打开浏览器的任务管理器(比如谷歌浏览器-> 更多工具 -> 任务管理器)
这里就是查看进程的地方,而且可以看到每个进程的cpu占用率和内存资源信息。
简单用比较官方的术语总结下:
- 进程是cpu资源分配的最小单位(是能拥有资源和独立运行的最小单位)
- 线程是cpu调度的最小单位(线程是建立在进程的基础上的一次程序运行单位,一个进程中可以有多个线程)
- 不同进程之间也可以通信。(比如网页是一个进程,qq是一个进程,在网页上使用快捷方式qq登录。网页怎么会知道你当前有没有登录qq的?这之间就涉及到了不同进程之间的通信)
- 一般讨论的单线程和多线程,都只是指在一个进程内的单和多。
4 浏览器是如何渲染进程的?与JS的单线程有什么联系?
在浏览器中打开一个网页相当于新起了一个进程,每个进程内又会有自己的多线程(当然,浏览器有自身的优化机制,当你开了很多空的标签页的时候,可能会发现多个空白标签页被合并成了一个进程)。比如页面的渲染,JS的执行,事件的循环,都会在这个进程内进行。(以下用比较官方的术语列举一些主要常驻线程)
扩散思考1:浏览器为什么要弄成多进程的?
4.1. GUI渲染线程
- 负责渲染浏览器界面,解析HTML,CSS,构建DOM树和RenderObject树,布局和绘制等。
- 当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行(扩展阅读:页面重绘和回流以及优化)
- 注意:GUI渲染线程和JS引擎线程是互斥的,当JS引擎执行时GUI线程会被挂起(想当与被冻结了),GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
.a {
width: 100px;
height: 100px;
background: #f60;
}
</style>
<script>
console.time('js执行')
for(var i = 0; i < 1000000000; i++) {
}
console.timeEnd('js执行')
</script>
</head>
<body>
<div class="a">a</div>
</body>
</html>
从这个例子中可以看到JS页面明显有一段空白期,也就证明了上面所说的当JS引擎执行时GUI线程会被挂起。
扩展思考:你可能以前听说并且一直是这么做的,JS调用不放在中,要放到网页底部