今天與一個同事爭論javascripe中間的線程機制,他爭論說javascript是有線程的,理由即便javascript中間的事件回調就是線程的實現,我的認爲在javascript中是沒有線程機制的
理由以下: javascript
引自《精通javascript》 john resig著: css
<script> while(!window.loaded); //some operation window.alert(); </script>
這段代碼的意圖就是想阻塞當前js線程, 直到頁面徹底加載完畢才執行後續操做。可是獲得的效果倒是瀏覽器暫停或者假死,可見在js中是不能用循環來暫停等待的。要實現這個效果必須採用回調: html
wndow.onload=funcrion(){ //some operation }
然而回調不是js語言中支持多線程的依據。咱們知道在windows中的回調消息機制是這樣的:windows把單擊事件和一個處理函數關聯起來,當咱們點擊了某個按鈕的時候,系統會調用這個單擊事件的處理函數。實際上,windows內部會維護一張事件處理表,這個表中單擊事件對應一個處理函數的函數指針。當點擊事件發生時,windows會調用這個函數指針所指向的函數。 java
那什麼是線程? 我想咱們應該從支持多線程的操做系統提及。多線程就是讓多個計算過程交替執行而且這個交替的時間片很短,短到咱們沒法感知。這就是爲何單處理器也能夠併發執行線程。操做系統會維護多個狀態的線程隊列,並決定採起何種調度算法來切換線程之間的執行. 算法
js中沒有線程的概念,或者說全部的操做到放在同一個線程(即單線程)中。那麼應該如何來模擬這個線程機制呢。既然js引擎沒有爲咱們維護一個線程列表,那麼咱們本身來實現(這個線程列表和調度算法):
windows
<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); } </script>
在這裏,咱們就能夠看見兩個子程序交替執行了,其實,若是用線程的眼光看的話,這裏是有三個線程的,一個是thread_one 一個是thread_two一個是main_thread(不過它先執行完)。這裏的主線程能夠當作操做系統中的進程(線程)管理器,由它來調度、切換和管理整個系統的線程。這裏main採用的」調度算法「很樸實,就是100秒的時間片輪轉,沒有優先級,沒有中斷。
下面給出一個完整的線程管理器例子: 瀏覽器
thread.js: 多線程
/** * 線程管理類 * @param _task 任務函數 * @param _delay 間隔時間(單位毫秒) * @param _times 執行次數(-1表示永遠執行) * @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; }else 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>