javascript多线程

页面导航:首页 > 网络编程 > JavaScript > javascript多线程

javascript多线程

来源: 作者: 时间:2016-01-22 08:40 【

最近在项目中用到了多线程编程,所以就此处深入产开学习。众所周知,javascript是单线程的语言,单线程意味着程序会按照指定的顺序按部就班的执行下去,遇到堵塞也无法越过。我们

最近在项目中用到了多线程编程,所以就此处深入产开学习。

众所周知,javascript是单线程的语言,单线程意味着程序会按照指定的顺序按部就班的执行下去,遇到堵塞也无法越过。我们简单地看看下面这个例子:

 

function f1(){
	console.time('time span');
}
function f2(){
	console.timeEnd('time span');
}
setTimeout(f1,100);
setTimeout(f2,200);
function waitForMS(n){
	var now = Date.now();
	while(Date.now() - now < n){}
}

waitForMs(500);


 

上面的代码中,按字面上来理解,就是执行100ms后执行f1,执行200ms后执行f2。可是真正的结果是:

\

也可以理解为忽略不计。为什么会这样呢?前面我已经提到,javascript是单线程的,程序一开始的时候,waitForMs函数就占用了进程,导致f1和f2两个函数不能按照指定的时间间隔执行。

 

虽然js是单线程的,但是js运行的环境,也就是浏览器,是支持多线程的。所以我们可以通过很多方式来实现javascript的多线程编程。

ajax

第一种就是利用ajax技术,ajax确实是异步的,XMLHttpRequest请求是由浏览器开启一个线程来完成异步操作。当请求的状态变更时,如果先前已设置回调,那么异步线程就产生状态变更事件放到javascript引擎的事件处理队列中等待处理。当浏览器空闲的时候队列中任务被处理,javascript引擎始终是单线程运行回调函数。

回调函数

第二种方式就是回调函数。回调函数也算是异步编程最基本的方式了。我们假设有两个函数,f1和f2.执行顺序为先执行f1,再执行f2。但是f1的执行时间有点长,我们希望可以在执行f1的同时也能够执行f2。

实现代码如下:

 

function f1(callback){
	//f1的内容需要耗费很多时间
	for(i=0;i<1000;i++){
		console.log(i);
	}
	callback();
}

function f2(){
	alert(2);
}

f1(f2); 
输出结果就是在f2弹框的同时,f1中的循环也在执行。
\

 

采用这种方式,我们把同步操作变成了异步操作,f1不会阻塞程序运行,相当于先执行程序的主要逻辑,将耗时的操作延迟执行。

回调函数的优点就是简单,容易理解和实现,缺点就是不利于代码的阅读和维护。比如以下代码:

 

function f1(f){
	alert(1);
	f();
}
function f2(f){
	alert(2);
	f();
}
function f3(){
	alert(3);
}

f1( function(){f2(f3)}  )

如果逻辑很复杂,就会形成传说中的回调地狱。

 

setTimeout

第三种办法就是利用setTimeout来模拟开启一个线程,其实并没有开启线程。javascript中定时器的原理还是有点复杂的。简单的可以理解为,setTimeout会将事件放入主程序的事件队列,如果主程序空闲了,就会第一时间调用setTimeout中的事件。 这种方式用得比较广泛,很多开源框架中都随处可见,比如bootstrap中:

setTimeout(function () { that.$element.trigger(slidEvent) }, 0) })
通过setTimeout将事件置于队列头部。


前面三种方式都是在过去被广泛运用的方式,随着HTML5的定稿,出现了一种新的概率。


WebWorkers

工作线程,也叫做WebWorkers,是HTML5中提出的对多线程的支持。Web Workers的三大主要特征:能够长时间运行,理想的启动性能以及理想的内存消耗。Web Workers允许开发人员编写能够长时间运行而不被用户所中断的后台程序,去执行事务或者逻辑,并同时保证页面对用户的及时响应。
Web Workers 为 Web 前端网页上的脚本提供了一种能在后台进程中运行的方法。一旦它被创建,Web Workers 就可以通过 postMessage 向任务池发送任务请求,执行完之后再通过 postMessage 返回消息给创建者指定的事件处理程序 ( 通过 onmessage 进行捕获 )。WebWorkers 进程能够在不影响用户界面的情况下处理任务,并且,它还可以使用 XMLHttpRequest 来处理 I/O,但通常,后台进程(包括 Web Workers 进程)不能对 DOM 进行操作。如果希望后台程序处理的结果能够改变 DOM,只能通过返回消息给创建者的回调函数进行处理。相信你已经急不可待了吧,马上上实例。首先,我们需要在客户端页面的javascript代码中new一个Worker实例出来,参数是需要在另一个线程运行的javascript文件名称。然后在这个实例上监听onmessage事件。主线程代码如下:






 
<script type=text/javascript> function init(){ var worker=new Worker('compute.js');//实例化一个WebWorker,参数为另一个线程的js文件名称 worker.onmessage=function(event){//event中有data属性,就是子线程中返回的结果数据 //把子线程返回的结果添加到div中 document.getElementById(result).innerHTML+=event.data+
; } } </script>
子线程通过postMessage方法就可以在两个线程间传递数据了。子线程compute.js代码如下:

 

var i=0;
function timedCount(){
	for(var j=0,sum=0;j<100;j++){
		for(var i=1;i<10000000;i++){
			sum+=i;
		}
	}
	postMessage(sum);//调用postMessage向主线程发送消息
}
postMessage(开始计算 +new Date());
timedCount();
postMessage(结束计算 +new Date());
最后结果如下:

\

 





 

Tags:

文章评论

最 近 更 新
热 点 排 行
Js与CSS工具
代码转换工具

<