Javascript执行机制
在HTML5以前,浏览器中JavaScript的运行都是以单线程的方式工做的,虽然有多种方式实现了对多线程的模拟(例如:Javascript 中的 setinterval 方法,setTimeout 方法等),可是在本质上程序的运行仍然是由 JavaScript 引擎以单线程调度的方式进行的。在 HTML5 中引入的工做线程使得浏览器端的 Javascript 引擎能够并发地执行 Javascript 代码,从而实现了对浏览器端多线程编程的良好支持。javascript
Javascript中的多线程 - WebWorker
HTML5 中的 Web Worker 能够分为两种不一样线程类型,一个是专用线程 Dedicated Worker,一个是共享线程 Shared Worker。两种类型的线程各有不一样的用途。java
专用型web workerweb
专用型worker与建立它的脚本链接在一块儿,它能够与其余的worker或是浏览器组件通讯,可是他不能与DOM通讯。专用的含义,就是这个线程一次只处理一个需求。专用线程在除了IE外的各类主流浏览器中都实现了,能够放心使用。
建立线程
建立worker很简单,只要把须要在线程中执行的JavaScript文件的文件名传给构造函数就能够了。编程
线程通讯
在主线程与子线程间进行通讯,使用的是线程对象的postMessage和onmessage方法。不论是谁向谁发数据,发送发使用的都是postMessage方法,接收方都是使用onmessage方法接收数据。postMessage只有一个参数,那就是传递的数据,onmessage也只有一个参数,假设为event,则经过event.data获取收到的数据。json
发送JSON数据
JSON是JS原生支持的东西,不用白不用,复杂的数据就用JSON传送吧。例如:跨域
处理错误
当线程发生错误的时候,它的onerror事件回调会被调用。因此处理错误的方式很简单,就是挂接线程实例的onerror事件。这个回调函数有一个参数error,这个参数有3个字段:message - 错误消息;filename - 发生错误的脚本文件;lineno - 发生错误的行。浏览器
销毁线程
在线程内部,使用close方法线程本身销毁本身。在线程外部的主线程中,使用线程实例的terminate方法销毁线程。多线程
HTML代码:并发
把它们放到相同的目录,运行页面文件,查看控制台,能够看到运行的结果。
这里还有一点,在主线程中,onmessage事件可使用另一种方式挂接:函数
我的以为很麻烦,不如用onmessage直接。
使用其余脚本文件
工做线程可使用全局方法importScripts来加载和使用其余的域内脚本文件或者类库。例以下面都是合法的使用方式:
导入之后,能够直接使用这些文件中的方法。看一个网上的小例子:
网上也有网友想到了利用这里的importScripts方法解决资源预加载的问题(浏览器预先加载资源,而不会对资源进行解析和执行),道理也很简单。
线程嵌套
在工做线程中还能够在建立子线程,各类操做仍是同样的。
同步问题
Worker没有锁的机制,多线程的同步问题只能靠代码来解决(好比定义信号变量)。
共享型SharedWebWorker
共享型web worker主要适用于多链接并发的问题。由于要处理多链接,因此它的API与专用型worker稍微有点区别。除了这一点,共享型web worker和专用型worker同样,不能访问DOM,而且对窗体属性的访问也受到限制。共享型web worker也不能跨越通讯。
页面脚本能够与共享型web worker通讯,然而,与专用型web worker(使用了一个隐式的端口通讯)稍微有点不一样的是,通讯是显式的经过使用一个端口(port)对象并附加上一个消息事件处理程序来进行的。
在收到web worker脚本的首个消息以后,共享型web worker把一个事件处理程序附加到激活的端口上。通常状况下,处理程序会运行本身的postMessage()方法来把一个消息返回给调用代码,接着端口的start()方法生成一个有效的消息进程。
看网上能找到的的惟一个例子:建立一个共享线程用于接收从不一样链接发送过来的指令,而后实现本身的指令处理逻辑,指令处理完成后将结果返回到各个不一样的链接用户。
HTML代码:
脚本文件代码:
在上面的共享线程例子中,在主页面即各个用户链接页面构造出一个共享线程对象,而后定义了一个方法 postMessageToSharedWorker 向共享线程发送来之用户的指令。同时,在共享线程的实现代码片断中定义 connect_number 用来记录链接到这个共享线程的总数。以后,用 onconnect 事件处理器接受来自不一样用户的链接,解析它们传递过来的指令。最后,定义一个了方法 execute_instruction 用于执行用户的指令,指令执行完成后将结果返回给各个用户。
这里咱们并无跟前面的例子同样使用到了工做线程的 onmessage 事件处理器,而是使用了另一种方式 addEventListener。实际上,前面已经说过,这两种的实现原理基本一致,只是在这里有些稍微的差异,若是使用到了 addEventListener 来接受来自共享线程的消息,那么就要先使用 worker.port.start() 方法来启动这个端口。以后就能够像工做线程的使用方式同样正常的接收和发送消息。
线程中能作的事:
1.能使用setTimeout(), clearTimeout(), setInterval(),clearInterval()等函数。
2.能使用navigator对象。
3.能使用XMLHttpRequest来发送请求。
4.能够在线程中使用Web Storage。
5.线程中能够用self获取本线程的做用域。
线程中不能作的事:
1.线程中是不能使用除navigator外的DOM/BOM对象,例如window,document(想要操做的话只能发送消息给worker建立者,经过回调函数操做)。
2.线程中不能使用主线程中的变量和函数。
3.线程中不能使用有"挂起"效果的操做命令,例如alert等。
4.线程中不能跨域加载JS。
线程也是须要消耗资源的,并且使用线程也会带来必定的复杂性,因此若是没有充足的理由来使用额外的线程的话,那么就不要用它。