Javascript 之單線程
javascript
Lastmod: 2019-12-13

首先看看下面的程式碼,會發現永遠跑不出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)來實現。

參考資料

comments powered by Disqus