almost 3 years ago

Javascript單線程

首先看看下面的程式碼,會發現永遠跑不出So sad,因為Javascript為單線程,雖然設定1秒過後isEnd為false,然後應該就直接跑出So sad,但因為被while一直佔住線程,因此永遠不會執行setTimeout事件,與console.log("So sad") 。

setTimeout(function () {
    isEnd = false;
}, 1000);
 while (isEnd);
 console.log("So sad");

Javascript的單線程是指一個瀏覽器行程(process)只有一個JS的執行線程(但不代表瀏覽器是單線程),同一個時段內只會有一段代碼在執行,代表一次只能完成一件事,如果有多件事,就代表你要排隊,一件一件的處理,如果有一件事卡死或要做很久,就代表下面的事永遠不會執行,優點是簡單,環境單純,但缺點是如果其中一個事件很耗時間,會拖慢整個程式執行。

Javascript將事件分為兩種同步(Synchronous)非同步(Asynchronous)來解決單線程的缺點。

同步(Synchronous)就是一個完成換下一個,下一個換成在換下下一個處理,程式執行順序與任務的排列順序是相同的,如下程式碼。

console.log(1);
console.log(2);
console.log(3);

輸出結果。

1
2
3

非同步(Asynchronous)
非同步為每一個任務都有一個CallBack,代表每個任務執行完後會執行該CallBack而不是執行下一個任務,因此程式執行順序與任務的排列順序是不相同的,下列以ajax為範例。

console.log(1);
$.ajax({
    url:"tests/1"
    success:function(data){
        console.log(2);
    }   
})
console.log(3);

輸出結果。

1
3
2

也就是說,假設該ajax很耗時,你可以不用等到ajax執行完,才跑console.log(3),而是先給它個callback等ajax執完後自動插入回線程中執行console.log(2)


為什麼Javascript是單線程?

Javascript最初做為瀏覽器腳本語言,主要用途在於和使用者戶動與操作DOM,也因此如果該語言為多線程語言就會發生不少混亂,例如Javascript有兩個線程,一個線程針對某個DOM節點新增某些內容,而另一線程為刪除該節點,那瀏覽器要以那個為主?所以為了避免這些亂,因此Javascript被設計為單線程語言。

HTML5提出了Web Worker的標準,web worker是運行在瀏覽器的後台,並且子線程完全由主線程控制,並且不得操作
DOM,所以該標準並沒有影響javascript為單線程的本質。

Javascript為單線程,又怎著非同步的執行呢?

通常這種語言為單線程,但又可以處理非同步的語言都有個一種共同點,那就是事件驅動event driven)機制,一般是由通過事件循環(Event Loop)事件隊列(Event Queue)來實現。

待續


參考資料

← 物件導向系列菜單11-『泛型(Generics)』 Javascript之Event Driven →
 
comments powered by Disqus