線程和單線程的概念:
線程:是操作系統能夠進行運算調度的最小單位。它被包含在進程之中,是進程中的實際運作單位。一條線程指的是進程中一個單一順序的控制流,一個進程中可以並發多個線程,每條線程並行執行不同的任務。
單線程:(上面有說:一條線程指的是進程中一個單一順序的控制流)就是在進程中只有一條線程,在程序執行時,所走的程序路徑按照連續順序排下來,前面的必須處理好,后面的才會執行。。
為什么JS是單線程?
引用阮一峰老師的回答 ---> JavaScript的單線程,與它的用途有關。作為瀏覽器腳本語言,JavaScript的主要用途是與用戶互動,以及操作DOM。這決定了它只能是單線程,否則會帶來很復雜的同步問題。比如,假定JavaScript同時有兩個線程,一個線程在某個DOM節點上添加內容,另一個線程刪除了這個節點,這時瀏覽器應該以哪個線程為准?
所以,為了避免復雜性,從一誕生,JavaScript就是單線程。
js的工作機制:
當線程中沒有執行任何同步代碼的前提下才會執行異步代碼,setTimeout是異步代碼,所以setTimeout只能等js空閑才會執行,但死循環是永遠不會空閑的,所以setTimeout也永遠不會執行。即使setTimeout為0,他也是等js引擎的代碼執行完之后才會插入到js引擎線程的最后執行。
瀏覽器的內核機制:
瀏覽器的內核是多線程的,一個瀏覽器一般至少實現三個常駐線程:
1. javascript引擎:是基於事件驅動單線程執行的,JS引擎一直等待着任務隊列中任務的到來,然后加以處理,瀏覽器無論什么時候都只有一個JS線程在運行JS程序。
2. GUI渲染線程:負責渲染瀏覽器界面,當界面需要重排、重繪或由於某種操作引發回流時,該線程就會執行。但需要注意 GUI渲染線程與JS引擎是互斥的,當JS引擎執行時GUI線程會被掛起,GUI更新會被保存在一個隊列中等到JS引擎空閑時立即被執行。
3. 事件觸發線程:當一個事件被觸發時該線程會把事件添加到待處理隊列的隊尾,等待JS引擎的處理。這些事件可來自JavaScript引擎當前執行的代碼塊如setTimeOut、也可來自瀏覽器內核的其他線程如鼠標點擊、AJAX異步請求等,但由於JS的單線程關系所有這些事件都得排隊等待JS引擎處理。
單線程和異步
看過很多關於 JavaScript 單線程與異步的介紹,大多數都引用這一類例子來說明:單線程就是排隊,前一個任務不完成后一個就不能開始,也就是常說的串行。 飯店點餐,所有人排隊,A顧客點完之后,廚房開始做,做完后A領到餐后,B再開始點餐,廚房又開始做…周而復始,這就是同步,點餐的時候廚房是閑着的,做菜的時候前台是閑着的。即單線程。所有人都能夠很好的理解,這樣做效率太低了!
換個思路,A點完餐后,到一旁等着,服務員將菜單遞給廚房,廚房開始做,然后繼續服務B顧客,當A顧客的餐做好之后,A來隊伍里插個隊,把餐領走。 聽到這里,效率高了很多嘛,整個餐廳沒有浪費一點工作力,大家都各司其事。然后作者就下了結論,這就是 JavaScript 的單線程與異步。
關於單線程和異步暫時就先記錄這些東西,后續會補充其他像event loop等相關知識。內容如有不准確,歡迎大家提出寶貴意見~~~