今天與一個同事爭論javascripe中間的線程機制,他爭論說javascript是有線程的,理由即使javascript中間的事件回調就是線程的實現,個人認為在javascript中是沒有線程機制的:
理由如下:
引自<<精通javascript>> john resig著:
- <script>
- <!--
- while(!window.loaded);
- //some operation
- window.alert();
- -->
- </script>
這段代碼的意圖就是想阻塞js當前線程。知道頁面完全載入以後菜執行下面接下來的操作,即“同步”,但是得到的效果是瀏覽器暫停或者死掉,可見在js中是不能用迴圈來暫停等待的;可見早javascript中要實現這個效果必須採用回調,即:
- wndow.onload=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" onclick='t1.start();'></input>
- <input type="button" value="sleep1" onclick='t1.sleep();'></input>
- <input type="button" value="resume1" onclick='t1.resume();'></input>
- <input type="button" value="abort1" onclick='t1.abort();'></input>
- <input type="button" value="start2" onclick='t2.start();'></input>
- <input type="button" value="sleep2" onclick='t2.sleep();'></input>
- <input type="button" value="resume2" onclick='t2.resume();'></input>
- <input type="button" value="abort2" onclick='t2.abort();'></input>
- <div id="t1">0</div> | <div id="t2">0</div>
- <input type="button" value="t1.timerID" onclick='alert(t1.timerID);'></input>
- <input type="button" value="t2.timerID" onclick='alert(t2.timerID);'></input>
- </body>
- </html>
我最先接觸線程就是來自於作業系統,由於js這門語言的特殊性,有人說是玩具語言的不嚴謹,有人說是靈活,褒貶不一,所以把自己對js線程的一些看法結合操作體統解釋一下,不敢保證對,也不敢保證表達的就是自己的意思,技術這玩意,有很多時候語言表達不了自己的認識,體會深了,就模模糊糊的認識到啦,要想做到表達給別人,還得功力加深,對於js我一直都是很迷茫的,閉包,面對對象,初始化,有很多地方值得大家探討,希望能向各位學習;(轉自請註明出處,csdn corey)