今天与一个同事争论javascripe中间的线程机制,他争论说javascript是有线程的,理由即使javascript中间的事件回调就是线程的实现,个人认为在javascript中是没有线程机制的:
理由如下:
引自<<精通javascript>> john resig著:
- <script>
- <!--
- while(!window.loaded);
- //some operation
- window.alert();
- -->
- </script>
这段代码的意图就是想阻塞js当前线程。知道页面完全加载以后菜执行下面接下来的操作,即“同步”,但是得到的效果是浏览器暂停或者死掉,可见在js中是不能用循环来暂停等待的;可见早javascript中要实现这个效果必须采用回调,即:
- wndow.οnlοad=funcrion(){
- //some operation
- }
然而,回调并不是js语言中支持多线程的依据,我们知道,在windows是支持回调消息机制的;当我们点击了某个按钮的时候系统会调用这个单击事件的处理函数,我想在windows中间是这么事件的他把一个处理函数绑定到了这个单击事件的出发上,维护一张事件处理表,这个表中间某个空间的单击事件对应一个处理函数的函数指针,当事件点击的时候,会调用这个函数指针指向的函数;
什么是线程,这个概念,我想我们应该从多线程的操作系统说起,多线程,就是让多个处理过程交替执行,并且这个交替的时间片很短,短到我们人类无法感知,这就是为什么单处理器也可以并发执行线程,而我们在上面看到的回调说实在的,就犹如一个方法的调用,等处理器函数调用完了以后再返回原程序段继续执行,我想这跟我们在操作系统里面的中断处理有很相似的
概念,我们知道,中断处理是硬件本来就支持的,而在单处理器的系统中,多线程是由操作系统来实现的,我多线程的操作系统下面,操作系统会认为的维护多个状态的线程队列,并决定采取何种轮转算法来切换线程之间的执行;他依靠重写时间中断处理器来在一个时间片的间隔里调用进程(线程)管理器来调节线程和进程之间的转换和执行;这就可见,类似于中断处理功能的回调功能并不能证明线程的存在(因为从上可以清晰的看见两者之间的关系);
以下的例子也可以清晰的证明js的所谓“线程”:
- <script language="javascript">
- <!--
- function main(){
- for(var index=0;index<10;index++){
- alert("main thread");
- setTimeout(secondary,20);
- }
- }
- function secondary(){
- alert("secondary");
- }
- main();
- -->
- </script>
由于没有进程的概念,这里本来应该是main和secondary交替执行的,变成了执行完main再执行secondary的贪婪调度;那按照这样理解的话,js中间没有线程的概念,我们如何自己来实现这个线程的机制呢,那么,就好像,我们在中断处理机制上面如何实现线程的概念是一样的;既然系统(js引擎)不给我们维护这个线程列表和调度,那么我们自己来实现(调度算法和)
- <script language="javascript">
- <!--
- var thread_one_time=0;
- var thread_two_time=0;
- function thread_one(){
- thread_one_time++;
- alert( thread_one_time);
- }
- function thread_two(){
- thread_two_time++;
- alert( thread_two_time);
- }
- }
- setInterval(thread_one,100);
- setInterval(thread_two,100);
- -->
- </script>
在这里,我们就可以看见两个子程序交替执行了,其实,如果用线程的眼光看的话,这里是有三个线程的,一个是thread_one 一个是thread_two一个是main_thread(不过已经执行完啦)别不信,不如你加修改成为这样就可以知道啦:
- <script language="javascript">
- <!--
- var thread_one_time=0;
- var thread_two_time=0;
- function thread_one(){
- thread_one_time++;
- alert( thread_one_time);
- }
- function thread_two(){
- thread_two_time++;
- alert( thread_two_time);
- }
- setInterval(thread_one,100);
- setInterval(thread_two,100);
- for(var i=0;i<10;i++){
- alert(i+"main");
- }
- -->
- </script>
所以这里的主程序你可以看成是一个贪婪主线程,相当于操作系统中间的进程管理器(时间中断处理器实现),他来调度和切换管理整个系统的线程队列,这里main采用的”调度算法“很朴实,就是100秒的时间片轮转,没有优先级,没有中断,没有........,
=js进程实现代码:
thread.js:
- /**
- * 线程管理类
- * @author zxub 2006-06-12
- */
- function Thread(_task,_delay,_times)
- {
- this.runFlag=false;
- this.busyFlag=false;
- this.taskArgs=Array.prototype.slice.call(arguments,3);
- if (_times!=undefined)
- {
- this.times=_times;
- }
- else
- {
- this.times=1;
- }
- var _point=this;
- this.timerID=-1;
- this.start=function()
- {
- if (this.runFlag==false)
- {
- this.timerID=window.setInterval(_point.run,_delay);
- this.runFlag=true;
- }
- }
- this.run=function()
- {
- if (_point.busyFlag) return;
- if (_point.times==-1)//无限循环
- {
- _task(_point.taskArgs);
- }
- else if (_point.times>0)
- {
- _task(_point.taskArgs);
- _point.times-=1;
- if (_point.times==0)
- {
- window.clearInterval(this.timerID);
- }
- }
- }
- this.sleep=function()
- {
- this.busyFlag=true;
- }
- this.resume=function()
- {
- this.busyFlag=false;
- }
- this.abort=function()
- {
- window.clearInterval(this.timerID);
- }
- }
thread.html:
- <html>
- <head>
- <title>测试</title>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <script type="text/javascript" src="thread.js"></script>
- <style type="text/css">
- <!--
- body,tr,td { font-size: 12px;}
- -->
- </style>
- </head>
- <body>
- <script>
- var func=function(_o)
- {
- document.getElementById(_o).innerHTML=parseInt(document.getElementById(_o).innerHTML)+1;
- }
- var t1=new Thread(func,50,121,"t1");
- var t2=new Thread(func,200,20,"t2");
- </script>
- <input type="button" value="start1" οnclick='t1.start();'></input>
- <input type="button" value="sleep1" οnclick='t1.sleep();'></input>
- <input type="button" value="resume1" οnclick='t1.resume();'></input>
- <input type="button" value="abort1" οnclick='t1.abort();'></input>
- <input type="button" value="start2" οnclick='t2.start();'></input>
- <input type="button" value="sleep2" οnclick='t2.sleep();'></input>
- <input type="button" value="resume2" οnclick='t2.resume();'></input>
- <input type="button" value="abort2" οnclick='t2.abort();'></input>
- <div id="t1">0</div> | <div id="t2">0</div>
- <input type="button" value="t1.timerID" οnclick='alert(t1.timerID);'></input>
- <input type="button" value="t2.timerID" οnclick='alert(t2.timerID);'></input>
- </body>
- </html>
我最先接触线程就是来自于操作系统,由于js这门语言的特殊性,有人说是玩具语言的不严谨,有人说是灵活,褒贬不一,所以把自己对js线程的一些看法结合操作体统解释一下,不敢保证对,也不敢保证表达的就是自己的意思,技术这玩意,有很多时候语言表达不了自己的认识,体会深了,就模模糊糊的认识到啦,要想做到表达给别人,还得功力加深,对于js我一直都是很迷茫的,闭包,面对对象,初始化,有很多地方值得大家探讨,希望能向各位学习;(转自请注明出处,csdn corey)