进程

time 2m
image.png
打开软件,比如qq音乐,打开qq音乐,点击快捷方式,将这个运行程序把它加载到内存中,正在运行中的程序,可以简单理解成进程
看电影、听音乐、聊天这些都需要数据,这些数据就是和程序相关的数据集合

time 5m19s
电脑出现的最初期都是单核的电脑,一个单核的cpu,可以上网、可以听音乐,可以同时做很多事情,为什么一个单核cpu能够同时做多件事情?
为了解决这件事,有一个算法,轮转时间片算法,非常快的时间内进行分段切片,这是单线单进程,单进程同样也可以模拟出一个多进程的做法,

image.png

单线程

time 6m30s
image.png
同属于一个进程的不同线程共享着进程中的资源
setTimeOut、ajax等都是调用同一进程的不同的线程,

多线程

time 8m45s
image.png

  • 一个进程中可以有多个线程,没有进程就没有线程,线程只能在进程的内部存在

举例说明

time 9m35s
image.png

  • 进程好比一个工厂,一个工厂有它相应的资源,原材料、工人等
  • 线程就像工厂里的工人
  • 进程与进程是互相独立的,意味着工厂和工厂之间是互相独立的
  • 工厂里面有工人,多个工人可以分工协作,多个线程是可以在一个进程当中完成协同任务的,多个工人协作加工一个件,一个物品,多个工人协作同时加工一个件一个物品
  • 进程,工厂与工厂之间不能同时加工一个件,比如流水线,汽车,喷漆的流水线、装轮子的流水线它们不能同时运行,只能先喷完漆,之后再装轮子,工厂也一样,一个工厂处理完件了,件变成别的样子了,之后交给另一个工厂,另一个工厂再继续组装
    • 比如inel通过硅造完cpu了,这是一个进程,但cpu不变成电脑没有意义,笔记本厂商再操作cpu,用cpu组装成笔记本电脑

浏览器是多进程的

time 13m

一个进程对应着一个程序,不会一个进程对应两个软件,但一个程序不一定对应一个进程,因为程序可以有多个进程,如果有些软件功能比较多,会有、可以有多个进程

所有浏览器都是多进程的

time 14m
image.png

浏览器常用进程

time 14m29s
image.png

css3 gpu硬件加速:调用gpu进程来启动硬件加速功能

浏览器渲染进程的线程

time 17m50s
image.png

1js引擎解析执行js代码的
2gui线程,不是gpu进程,进程耗费资源,渲染网页没有必要单独开个进程

js引擎线程与gui线程是互斥的

time 23m

  1. <button>button</button>
  2. <script !src="">
  3. var button=document.getElementsByTagName('button')[0];
  4. button.onclick=function() {
  5. console.log(1);
  6. while (1){
  7. }
  8. }
  9. </script>

按钮点击发生变化,是因为点击按钮时样式css发生了改变,gui线程启动,视觉发生了变化
第一次可以看见点击的视觉变化,并打印1,第二次点击,视觉看不到变化,因为第一次点击运行while(1),死循环了,js代码一直运行,js引擎线程一直运行,gui线程不会运行
这个例子说明了互斥关系

time 25m
其它线程
image.png
这三个线程对应用来处理异步数据的,准确说是处理事件队列的

为什么js引擎是单线程的?

time 29m
从设计角度来看,js就不能是多线程的。js设计的初衷就是使得浏览器不只是静态页面,而是可以动起来,可以交互。怎么样才能交互?操作什么才可以,处理dom才可以,所以说js设计之初就是为了处理dom操作的。

time 31m

  1. <button>button</button>
  2. <script src="index.js"></script>
  3. <script src="index1.js"></script>

比如index、index1都是处理button的,假设它们同时运行,是多线程的,index修改button、index1删除button,势必引起冲突,不可以控制、预见的冲突
所以js单线程的原因是为了避免dom冲突

单线程处理大数据量

time 33m
js引擎用单线程解决了dom冲突,但单线程也有短板,计算能力有限,计算能力是处理事物的能力
image.png

解决方案不止两种,有多种
ssr服务端渲染技术
ssr计算交给后端,前端只做渲染,这就是前后端分离。

time 38m
webworker html5新增api
webworker可以开一个新的子线程,不是js引擎开的,js引擎是单线程,开不了,是浏览器browser进程开的,帮js引擎开了一个子线程,是在js单线程下面开的一个子线程,webworker 是不能够访问dom的

time 42m
但如果数据量不大,也不小呢?ssr麻烦,webworker 新开子线程耗费性能。单线程本质的问题并没有得到解决
单线程的解决方案就是异步

time 44m
总结
image.png
js引擎是1单线程的,2可以异步执行

异步

time 44m45s
单线程是一段时间只能处理一件事情,js引擎是单线程的,如果js代码里面有耗时操作,导致js引擎线程一直运行,gui线程得等js引擎运行结束才能运行,如果等待时间长,就会一直没有页面加载,体验不好

计算机语言里面的异步是同一时间可以处理两件事情,但js引擎是单线程,不能这样做,所以这个异步不是真正意义上的异步,本质上不是异步,而是模拟的,用单线程模拟异步,单线程通过事件驱动模拟异步
它是通过事件驱动的方式模拟的一个异步的方式,所有单线程语言实现异步,基本都是通过事件驱动。

node环境与浏览器环境

time 47m52s
image.png
这些都是浏览器提供的,是在浏览器环境中,如果环境方式变化会有不同,比如node
如果环境发生了变化,哪怕js引擎线程不变,对应的异步方式也会发生变化

js引擎本质上是v8引擎,但执行环境如果不在浏览器,不是浏览器提供的相应的事件处理线程,对应着异步处理方式也改变
例子node里面会有

time 51m
image.png

所有的js代码都是通过执行栈执行的,所以js代码运行,任务进入执行栈

time 55m
调试方法
image.png

time 58m

  1. function test(){
  2. var test1=function (){
  3. console.log(2);
  4. }
  5. test1();
  6. console.log(1);
  7. }
  8. test();
  9. /*2 1*/
  1. function test(){
  2. console.log("3")
  3. debugger;
  4. var test1=function (){
  5. console.log(2);
  6. }
  7. test1();
  8. console.log(1);
  9. }
  10. test();

3打印了,但在这里中断
image.png

time59m35s
image.png

image.png
点击这个按钮
点击两次

image.png
test1执行

点击这个按钮也可以,最好点击这个按钮
test1执行,放入执行栈,在上面
image.png

test1运行完成,test1消失,所有命令都是执行栈中执行的,
image.png

webapi

time 1h4m06s
image.png
回调函数不一定是异步代码
异步代码是回调函数,除了async

time 1h5m35s
image.png
比如这个代码,异步代码在cb1中出现
同步代码,异步代码
setTimeout定时器触发线程,属于异步操作

image.png
3ajax 4setTimeout 5event事件处理函数 比如onclick

步骤分析

time 1h12m31s
4-剖析JavaScript的执行机制 - 图24

image.png

console要运行前,进入调用堆栈,js代码都会进入调用栈
同步代码进入调用栈
image.png

执行console
image.png

console执行完了,从调用栈移除
image.png

异步代码
time 1h13m49s
setTimeout函数执行进入调用栈,虽然他是异步,但它也是一个函数执行,函数执行进入调用栈中
image.png

time 1h14m06
setTimeout函数执行,因为是异步代码,所以浏览器创建一个计时器计时,webapi启动
执行setTime代码时,会调用相应的异步线程,注册webapi相应的回调函数,名字是timer,因为是定时器触发线程所以是timer,这个回调函数所对应的执行内容是cb1,然后等待事件被触发
image.png

setTimeout执行完成,从调用栈删除
setTimeout执行的作用就是开始计时,告诉webapi要开始计时了,告诉webapi计时5000ms,并把setTimeout中的回调函数给webapi(类似把它们作为实参给webapi,webapi里面有形参),干成这几件事情的时候,setTimeout就已经完成任务了,所以就执行完了
所以,综上所述,计时开始的时候setTimeout已经完成任务了,所以就执行完了
计时5000ms是webapi运行发生的事情,setTimeout不用等5000ms
image.png

image.png

image.png

image.png

time 1h18m30s
5s后,webapi中的timer cb1,进入Callback Quene中

image.png
这三个说的都是一个东西,就是叫法不一样,比如第一名、冠军、first说的都是一样的东西

image.png

time 1h20m54s
事件循环从Callback Quene中取出事件,把cb1取出放到call stack中
什么叫事件循环、事件轮询呢?
应该叫事件轮询,不停的循环
call stack调用栈,也可以简单说同步队列,先看调用栈里任务执行完了吗,调用栈没有任务,执行完了,之后看看任务队列(Callback Quene)有没有任务,有任务,会将任务队列中的任务的首位推入到当前的主进程当中
应该是一个事件轮询的过程,cb1执行完,看见(查询)call stack里面没有了,看(查询)任务队列里面有有没有,循环多次,询问多次,所以应该叫事件轮询,也可以理解成不停的、一直监听同步队列(call stack)和异步队列Callback Quene
循环只有一次,轮询是反复的循环

image.png

time 1h26m37s
cb1执行,cb1是个函数,回调函数,函数中有console语句,函数中语句执行进入调用栈

image.png
image.png

image.png

image.png

回顾
4-剖析JavaScript的执行机制 - 图42

总结

time 1h27m54s
轮询相当于一个哨兵,一直来回巡逻,一直来回看调用栈和任务队列,看调用栈为空,就看任务队列有没有东西,有东西,拿出看到的第一个,其它的不看,有就行,不看有几个,把看到的第一个取出来给调用栈

webapi注册回调并挂起,在这里注册timer回调,里面有cb1函数,并挂起,挂起就等待当前的回调执行,比如等待5000ms,5000ms之后,把它推到当前的事件队列当中

练习

time 1h29m53s
image.png
setTimeout挂起,等待当前触发,放入任务队列,任务队列等待调用栈里面执行完了再执行
setTimeout有延迟,规定时间最短4ms,就是0.004s
执行时间可以简单理解成硬件的读写速度
写0(4ms)到30都行

time 1m37m44s
image.png

1000ms不是真正的1000ms,因为等待同步代码执行完也需要时间,如果执行同步代码的数据超过了1000ms的时候,进入任务队列时,调用栈还没有清空,同步代码没有运行完,需要等待
如果延迟不大没有事,延迟大了很有可能是同步代码阻塞引起的

扩展总结思考

https://segmentfault.com/a/1190000017419328

因为js引擎是单线程,并且与gui是互斥的,所以需要解决执行js代码耗时,导致gui不能运行的问题
有同步代码,也有异步代码,浏览器处理它们的方式不一样

调用栈、webapi、任务队列这三个的关系