单线程和异步

352 阅读5分钟

这是我参与8月更文挑战的第24天,活动详情查看:8月更文挑战

前言:小白科普文,大神请忽略

线程

线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位

关于线程和进程之间的差别,推荐看 : www.ruanyifeng.com/blog/2013/0…

js是单线程的

js中永远单线程的, JS在一段时间内只能执行一部分代码, 那么, 当有多块代码需要执行时, 就需要排队等候了. JS的主进程调用栈是同步的(单线程,一次只能做一件事) 所有的任务都是顺序执行,

浏览器是多线程

但是js运行在浏览器中,浏览器是事件驱动型的!

1.GUI渲染线程

   GUI渲染线程负责渲染浏览器界面HTML元素,解析HTML,CSS,构建DOM树和RenderObject树,布局和绘制等。

  当界面需要重绘(Repaint)或由于某种操作引发回流(重排)(reflow)时,该线程就会执行。

  在Javascript引擎运行脚本期间,GUI渲染线程都是处于挂起状态的,也就是说被”冻结”了,GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。

2.JavaScript引擎线程

  JavaScript引擎,也可以称为JS内核,主要负责处理Javascript脚本程序,例如V8引擎。

  JS引擎一直等待着任务队列中任务的到来,然后加以处理,一个Tab页(renderer进程)中无论什么时候都只有一个JS线程在运行JS程序(单线程)。

  注意⚠️:GUI渲染线程和JavaScript引擎线程互斥!

  由于JavaScript是可操纵DOM的,如果在修改这些元素属性同时渲染界面(即JavaScript线程和UI线程同时运行),那么渲染线程前后获得的元素数据就可能不一致了。

  因此为了防止渲染出现不可预期的结果,浏览器设置GUI渲染线程与JavaScript引擎为互斥的关系,当JavaScript引擎执行时GUI线程会被挂起,GUI更新会被保存在一个队列中等到引擎线程空闲时立即被执行。

  如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。

3.事件触发线程

  当一个事件被触发时该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理。

  这些事件可以是当前执行的代码块如定时任务、也可来自浏览器内核的其他线程如鼠标点击、AJAX异步请求等,但由于JS的单线程关系所有这些事件都得排队等待JS引擎处理。

4.定时触发器线程

  setIntervalsetTimeout所在线程

  浏览器定时计数器并不是由JavaScript引擎计数的, 因为JavaScript引擎是单线程的, 如果处于阻塞线程状态就会影响记计时的准确。

  通过单独线程来计时并触发定时(计时完毕后,添加到事件队列中,等待JS引擎空闲后执行)

  注意,W3C在HTML标准中规定,规定要求setTimeout中低于4ms的时间间隔算为4ms。

1s=10^3ms(毫秒)=10^6μs(微秒)

5.异步http请求线程

  在XMLHttpRequest在连接后是通过浏览器新开一个线程请求。

异步篇

实现异步的方法

  1. 回调函数
  2. 事件监听
  3. 发布订阅模式
  4. Promise
  5. Generator (ES6)
  6. async (ES7)

异步案例

从ajax请求,我们看同步和异步的区别 image.png

此案例,基本可以体现异步和同步的区别

异步的解释:

异步的另外一种含义是计算机多线程的异步处理。与同步处理相对,异步处理不用阻塞当前线程来等待处理完成,而是允许后续操作,直至其它线程将处理完成,并回调通知此线程。

但此处需要明确的是:异步与多线程与并行不是同一个概念

异步事件是否会受到单线程的影响?

   答案是肯定的: 异步事件也必须排队等候(即异步事件对应的JS回调函数, 也必须排队等候执行, 如何排队则因浏览器而异)

看代码,有图有真相

<script>
alert('begin')
setTimeout(function() {
    alert('Timeout');
},0);
alert('over');
</script>

结果顺序begin ,over ,timeout

浏览器执行异步示意图

将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中,再由JavaScript引擎执行。

image.png

主栈空闲,Event触发,Event Loop机制把队列里排在前面的回调压入主栈

image.png

通俗易懂的解释

  • 同步:提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事
  • 异步: 请求通过事件触发->服务器处理(这是浏览器仍然可以作其他事情)->处理完毕
  • 同步就是你叫我去吃饭,我听到了就和你去吃饭;如果没有听到,你就不停的叫,直到我告诉你听到了,才一起去吃饭。
  • 异步就是你叫我,然后自己去吃饭,我得到消息后可能立即走,也可能等到下班才去吃饭。
  • 举个例子 打电话时同步 发消息是异步