一、进程与线程
进程:正在执行的程序为一个进程。
程序的一次运行,它会占用一片独立的内存空间。称为进程
线程:线程是进程内一个独立的执行单元。
1、一个进程中至少一个运行的线程,称为主线程。进程启动后自动创建。
2、应用程序的代码必须运行线程中。
3、在一个进程内同时有多个线程运行。
4、线程池(Thread pool):保存多个线程对象的容器,实现线程对象的反复使用。
1.1 单线程与多线程区别
在一个进程内至少有一个线程运行,也可以同时有多个线程运行。
多线程:
优点:能有效提高CPU的利用率
缺点:1、线程并发问题
2、线程切换、线程创建的时间开销
单线程:
优点:顺序编码比较简单
缺点: 效率低
1.2 浏览器是单进程还是多进程?
浏览器是单进程运行还是多进程运行?
1、有的是单进程:火狐、老版IE
2、有的是多进程:谷歌、新版IE
>>>>>> 查看应用程序是多进程还是单进程
JS是单线程运行。
但是使用H5中的Web Workers可以多线程运行。
二、浏览器内核
浏览器内核:支持浏览器运行的最核心的程序。
2.1 浏览器内核
不同浏览器的内核可能不一样:
Chrome、Safari:webkit内核
firefox:Gecko
IE:Trident
360、国内其他浏览器:Trident+webkit
2.2 浏览器内核模块组成部分
内核有很多模块组成
主线程:
1、js引擎模块:负责js的编译与运行
2、html、css文档解析模块:负责页面文本的解析
3、DOM、CSS模块:负责dom、css在内存中的处理,解析为DOM树
4、布局和渲染模块:参照DOM中对象,负责页面的布局和渲染
分线程:
1、定时器管理模块:负责定时器的管理
2、DOM事件管理模块:负责事件的管理
3、Ajax管理模块:负责ajax请求
三、事件循环模型(JS单线程运行原理)
3.1 定时器
1、定时器真的是定时执行的么?
定时器并不是真正的定时执行。一般会延时一丁点时间运行。
2、定时器回调函数是哪一个线程在执行?
在主线程中执行的, js是单线程的。
3、定时器是如何实现的?
事件循环模型
1)JS是单线程执行的
1、我们将代码分为初始化代码和回调代码。
初始化代码就是主函数代码,包括绑定事件、开启定时任务等。
回调代码指回调函数。
2、JS引擎执行代码流程:
1) 先执行初始化代码,即主函数代码(包含设置定时器、绑定监听、Ajax调用等)
2) 在初始化代码执行完毕后,后面在某个时刻才会触发回调函数。
3、JS是单线程运行,只在主线程执行。
1) JS是单线程运行,但是浏览器是多线程运行。
2) JS引擎执行主函数代码,会将回调函数交给浏览器的事件模块处理。
当回调函数被触发时,浏览器事件模块会将回调函数放入到队列中等待执行。
当主函数代码执行完毕后,JS引擎会从队列中取出回调函数在栈中执行。
>>>>>> 证明js是单线程运行
alert("xx") // 暂停当前主线程的运行,同时暂停计时
// 点击确定后,恢复程序执行和计时
如下案例,
先会执行alert("main"),不点击弹窗确定,则延时函数一直不会执行。
点击弹窗确定后,延时函数才会恢复计时执行。
console.log("123")
setTimeout(function(){
alert("123")
},0);
alert("main")
>>>>>> JS为什么设置为单线程执行,而不是多线程执行
作为浏览器脚本语言,JS的主要用途就是与用户交互,以及操作DOM。
这决定了它只能是单线程。如果设置为多线程,就会带来很复杂的同步问题。
3.2 事件循环模型(JS单线程运行原理)
+++ 事件循环模型由两部分组成
1、事件管理模块(定时器/DOM事件/Ajax管理模块)
2、回调队列
+++ 流程
1、执行初始化代码,将绑定的回调函数交给事件管理模块管理
1) 定时器回调函数交给定时器管理模块
2) DOM事件回调函数交给DOM事件管理模块
3) Ajax回调函数交给Ajax事件管理模块
2、事件执行时,管理模块会将回调函数添加到队列中
3、只有当初始化代码执行完毕后(可能要一定的时间),JS引擎才会从任务队列中循环取出回调函数放入执行栈中执行。
【事件循环模型处理流程指的是定时函数、事件绑定函数、Ajax的执行流程】
>>>>>> JS运行流程
1、JS引擎执行主函数代码,在stack中执行,即在执行上下文栈执行。
由于JS是单线程,所以只有一个执行上下文栈。
2、JS引擎执行主代码,将绑定的回调函数交给事件管理模块管理。
事件管理模块主要包括:定时器管理模块、事件管理模块、Ajax管理模块
3、当回调函数被触发时,事件管理模块会将回调函数放入到队列中等待执行。
4、当主函数代码执行完毕,JS引擎会从任务队列中取出回调函数放入到栈中执行(一个接一个)
3.3 JS线程
1、JS是单线程执行的。回调函数也是在主线程执行。
2、H5提出了多线程方案:Web Workers
3、只能在主线程更新界面,即操作DOM。
三、Web Workers
H5规范提供了JS分线程的实现,取名为Web Worksers
相关API
Worker:构造函数,加载分线程执行的js文件
Worker.prototype.postMeaasge:开启线程,并另外一个线程发送信息
Worker.prototype.onmessage:用于接收另一个线程的回调函数
不足:
Worker内代码不能操作DOM,即Worker内代码看不到window对象。
不能跨域加载JS
不是每个浏览器都支持分线程。
>>>>>> index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript" src="a.js" ></script>
<script>
function show(){
//加载线程JS文件
var worker=new Worker("a.js");
//绑定接收分线程的数据的监听
worker.onmessage=function(event){
console.log("主线程接收数据:"+event.data)
}
//向分线程发送数据
worker.postMessage(123);
}
</script>
</head>
<body>
<button onclick="show()">点击</button>
</body>
</html>
>>>>>> a.js
Worker内代码看不到window对象,所以不能操作DOM
function tt(){
console.log("123")
}
var onmessage=function(event){
console.log("分线程接收数据:"+event.data);
tt();
//向主线程发送数据
postMessage("111")
}