Javascript的单线程与多线程

目录

 

一、浏览器的线程和进程

1.浏览器的线程

2.浏览器是多进程的

二、Javascript是单线程的

1.异步Ajax也是单线程的

2.setInterval和setTimeout本质上并不是多线程

三、Web Worker支持多线程

1.多线程间数据交互

2.Web Worker的兼容性

3.Web Worker的使用限制

3.1同源限制

3.2访问限制

4.Web Worker的应用场景

总结


 

一、浏览器的线程和进程

1.浏览器的线程

一个浏览器通常由以下几个线程:

 

  • 渲染引擎线程:负责页面的渲染
  • JS引擎线程:负责JS的解析和执行
  • 定时触发器线程:处理定时事件,比如setTimeout,setInterval
  • 事件触发线程:处理DOM事件
  • 异步http请求线程:处理http请求

浏览器中有三个常驻的线程,分别是JS引擎线程、界面渲染线程、事件触发线程。

需要注意的是,渲染线程和JS引擎线程是不能同时进行的。渲染线程在执行任务的时候,JS引擎线程会被挂起。因为JS可以操作DOM,若在渲染中JS处理了DOM,浏览器可能就混乱了。

2.浏览器是多进程的

Google或IE浏览器每打开一个tab标签页就会有一个子进程,具体可打开任务管理器查看。

 

二、Javascript是单线程的

浏览器端JavaScript是以单线程的方式执行的,也就是说JavaScript和UI渲染占用同一个主线程,那就意味着,如果JavaScript进行高负载的数据处理,UI渲染就很有可能被阻断,浏览器就会出现卡顿,降低了用户体验。

1.异步Ajax也是单线程的

Ajax是单线程的,因为JavaScript是单线程的,Ajax属于JavaScript范畴,因此Ajax是单线程的。

Ajax请求确实是异步的,JS引擎执行异步代码而不用等待,是因为有消息队列事件循环,这请求是由浏览器新开一个线程请求。浏览器中很多行为是异步的,当一个异步事件发生的时候,它就进入事件队列,浏览器有一个内部的消息循环,Event Loop(事件循环),会轮询大的事件队列并处理事件,只有前面的处理完毕了,空闲了才会执行这个事件,而JavaScript引擎始终是单线程运行回调函数。

2.setInterval和setTimeout本质上并不是多线程

1.setTimeout,setInterval并不是多线程,只是一个定时的事件触发器,它们在合适的时间把一些JS代码塞到JS引擎的队列中。

2.setTimeout(aFunction, 0),这行代码看似的意思是在0秒之后执行aFunction, 但这并不意味着立即执行。其它真正的意思是立刻把aFunction的代码放到当前JS引擎的队列中。所以当前代码块执行完成之前,aFunction的代码是得不到执行的。

3.在一个事件的响应代码执行完成之后,即使队列中有待执行的代码,浏览器也会先执行页面渲染和响应事件,完成之后再执行队列中的代码。

 

三、Web Worker支持多线程

web worker 是运行在后台的 JavaScript,独立于其他脚本,不会影响页面的性能。您可以继续做任何愿意做的事情:点击、选取内容等等,而此时 web worker 在后台运行。

1.多线程间数据交互

Web Worker线程和原本的JS线程互不影响.

两个线程之间是通过onPostMessage 和 onMessage这两个函数来进行通讯的。其中onPostMessage(data)的参数是你要传递的数据,而onMessage是一个回调函数,只有在接受到数据时,onMessage会被回调,onMessage有一个隐藏的参数,那就是event,我们可以用event.data获取到传递过来的数据来更新主线程。

2.Web Worker的兼容性

Javascript的单线程与多线程_第1张图片

3.Web Worker的使用限制

3.1同源限制

分配给Worker 线程运行的脚本文件(worker.js),必须与主线程的脚本文件(main.js)同源。

3.2访问限制

Worker子线程所在的全局对象,与主线程不在同一个上下文环境,无法读取主线程所在网页的 DOM 对象,也无法使用document、window、parent这些对象,global对象的指向有变更,window需要改写成self,不能执行alert()方法和confirm()等方法,只能读取部分navigator对象内的数据。另外chrome的console.log()倒是可以使用,也支持debugger断点,增加调试的便利性。

4.Web Worker的应用场景

1、使用专用线程进行数学运算
Web Worke设计的初衷就是用来做计算耗时任务,大数据的处理,而这种计算放在worker中并不会中断前台用户的操作,避免代码卡顿带来不必要的用户体验。例如处理ajax返回的大批量数据,读取用户上传文件,计算MD5,更改canvas的位图的过滤,分析视频和声频文件等。worker中除了缺失了DOM和BOM操作能力以外,还是拥有非常强大的js逻辑运算处理的能力的,相当于nodejs一个级别的的运行环境。

2、高频的用户交互
高频的用户交互适用于根据用户的输入习惯、历史记录以及缓存等信息来协助用户完成输入的纠错、校正功能等类似场景,用户频繁输入的响应处理同样可以考虑放在web worker中执行。例如,我们可以 做一个像Word一样的应用:当用户打字时后台在词典中进行查找,帮助用户自动纠错等等。

3、数据的预取
对于一些有大量数据的前后台交互产品,可以新开一个线程专门用来进行数据的预取和缓冲数据,本地web数据库的行写入和更改,长时间持续的运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断,也有利于随时响应主线程的通信。也可以配合XMLHttpRequest和websocket进行不断开的通信,实现守卫进程。

最后,web worker有了多线程的形(有了多线程的用法),但还不具备多线程的神(不具备线程通信、锁等后台线程的基本特性),web worker的本质是支持我们把数据刷新与页面渲染两个动作拆开执行(不使用web worker的话这两个动作在主线程中是线性执行的)。


总结

1.Javascript是单线程的。

2.JS的异步Ajax和setInterval/setTimeout函数本质上也是单线程的。

3.Web Worker才是真正的多线程。但是使用上会有一些限制,如无法读取主线程所在网页的 DOM 对象,也无法使用document、window、parent这些对象。

你可能感兴趣的:(web前端,javascript,多线程)