摘要:?jiǎn)尉€程定義單線程在程序執(zhí)行時(shí),所走的程序路徑按照連續(xù)順序排下來(lái),前面的必須處理好,后面的才會(huì)執(zhí)行。單線程就是進(jìn)程只有一個(gè)線程。
單線程定義
單線程在程序執(zhí)行時(shí),所走的程序路徑按照連續(xù)順序排下來(lái),前面的必須處理好,后面的才會(huì)執(zhí)行。 單線程就是進(jìn)程只有一個(gè)線程。 多線程就是進(jìn)程有多個(gè)線程。Javascript 單線程
其實(shí)這里Javascript的單線程運(yùn)行機(jī)制和上面單線程定義是一個(gè)執(zhí)行流程,它只有一個(gè)主線任務(wù),比如:前面有一條河中間只有一根木棍,想要過(guò)河只能從一邊按順序走,單個(gè)單個(gè)的執(zhí)行,如果從兩頭一起過(guò)河Javascript的單線程就會(huì)造成阻塞,這里只是舉例了一個(gè)簡(jiǎn)單的解釋示例,雖然JavaScript是單線程的且效率太低只能按部就班的一步步走,可是瀏覽器內(nèi)部不是單線程的。你的一些I/O操作、定時(shí)器的計(jì)時(shí)和事件監(jiān)聽(tīng)(click, keydown...)等都是由瀏覽器提供的其他線程來(lái)完成的任務(wù)隊(duì)列和事件循環(huán)
調(diào)用棧
代碼在運(yùn)行過(guò)程中,會(huì)有一個(gè)叫做調(diào)用棧的概念。調(diào)用棧是一種棧結(jié)構(gòu),它用來(lái)存儲(chǔ)計(jì)算機(jī)程序執(zhí)行時(shí)候其活躍子程序的信息。(比如什么函數(shù)正在執(zhí)行,什么函數(shù)正在被這個(gè)函數(shù)調(diào)用等等信息)
代碼示例
function expale(a) { return a+1 } console.log(expale(1))
上面的例子我們創(chuàng)建了一個(gè)簡(jiǎn)單的函數(shù),然后利用console打印并執(zhí)行了這個(gè)函數(shù),在console這里執(zhí)行的時(shí)候已經(jīng)形成了一個(gè)棧,我們也可以比喻成一個(gè)比較大的盒子,console.log(expale(1))就是底部的一個(gè)盒子,然后expale(1)會(huì)變成另一個(gè)盒子落在console.log(expale(1))上面這就形成了棧,其實(shí)就是上面所說(shuō)到的存儲(chǔ)計(jì)算機(jī)程序執(zhí)行時(shí)候其活躍子程序的信息。最后只想說(shuō)因?yàn)樗菃尉€程
任務(wù)隊(duì)列
宏任務(wù)隊(duì)列: setTimeout setInterval setImmediate I/O UI rendering (瀏覽器渲染) 微任務(wù)隊(duì)列: process.nextTick(下一個(gè)事件輪詢的時(shí)間點(diǎn)上執(zhí)行) Promise Object.observer MutationObserver(監(jiān)視 DOM 變動(dòng)的接口) console.log("11221121"); // 微任務(wù) Promise.resolve().then(() => { console.log("p 1"); }); // 宏任務(wù) setTimeout(() => { console.log("setTimeout"); }, 0);
等宏任務(wù)執(zhí)行完(全局執(zhí)行完)就會(huì)開始執(zhí)行整個(gè)微任務(wù)隊(duì)列
事件循環(huán)
如上圖所示stack存儲(chǔ)著要執(zhí)行的任務(wù),下面黃色的onclick函數(shù)就是消息隊(duì)列,一旦有異步響應(yīng)就會(huì)被推入到該隊(duì)列中。比如:用戶的點(diǎn)擊事件,setTimeout等等,然后再進(jìn)入到stack棧中,然后再有任務(wù)進(jìn)入消息隊(duì)列,再執(zhí)行這樣就形成了事件循環(huán) 單線程從任務(wù)隊(duì)列中讀取任務(wù)是不斷循環(huán)的,每次棧被清空后,都會(huì)在任務(wù)隊(duì)列中讀取新的任務(wù),如果沒(méi)有新的任務(wù),就會(huì)等待,直到有新的任務(wù),這就叫任務(wù)循環(huán)。因?yàn)槊總€(gè)任務(wù)都由一個(gè)事件所觸發(fā),所以也叫事件循環(huán)。異步機(jī)制
如果函數(shù)是異步的,發(fā)出調(diào)用之后,馬上返回,但是不會(huì)馬上返回預(yù)期結(jié)果。調(diào)用者不必主動(dòng)等待,當(dāng)被調(diào)用者得到結(jié)果之后會(huì)通過(guò)回調(diào)函數(shù)主動(dòng)通知調(diào)用者,上面咱們也簡(jiǎn)單的介紹了棧和任務(wù)隊(duì)列,以及簡(jiǎn)單的事件循環(huán),做了一些鋪墊
代碼
function send () { ajax()... } send()
上面是一段ajax的一段代碼執(zhí)行,這時(shí)候單線程里面已經(jīng)有這個(gè)任務(wù)了,當(dāng)我們執(zhí)行send()之后這個(gè)任務(wù)在頁(yè)面中其實(shí)已經(jīng)完成了,但是我們無(wú)法拿到它的結(jié)果,在JavaScript中通過(guò)回調(diào)函數(shù)在耗時(shí)操作執(zhí)行完成后把相應(yīng)的結(jié)果信息傳遞給回調(diào)函數(shù),通知執(zhí)行JavaScript代碼的線程執(zhí)行回調(diào),這也就應(yīng)上面那句話“不會(huì)馬上返回預(yù)期結(jié)果”
瀏覽器常駐線程渲染引擎線程:顧名思義,該線程負(fù)責(zé)頁(yè)面的渲染
JS引擎線程:負(fù)責(zé)JS的解析和執(zhí)行
定時(shí)觸發(fā)器線程:處理定時(shí)事件,比如setTimeout, setInterval
事件觸發(fā)線程:處理DOM事件
異步http請(qǐng)求線程:處理http請(qǐng)求
在這里我們要注意js引擎和渲染線程是不能同時(shí)進(jìn)行的,渲染要在js引擎之前
代碼setTimeout(function(){ console.log("timer a"); }, 0) for(var j = 0; j < 5; j++){ console.log(j); } setTimeout(function(){ console.log("timer b"); }, 0) console.log("click begin");
setTimeout的作用是操作者可以設(shè)定時(shí)間插隊(duì),我們可以把它想象成一個(gè)會(huì)員,有特殊待遇,你可以插隊(duì),但是這里的setTimeout(fn, 0)是將函數(shù)插入執(zhí)行隊(duì)列,等待執(zhí)行,但是它不會(huì)立即執(zhí)行,不是立即執(zhí)行,下面的代碼就是一個(gè)很好的例子 b a
setTimeout(function() { console.log("a") }, 0) console.log("b")
總結(jié)
其實(shí)JavaScript單線程并不孤單(瀏覽器的其他線程幫助它),它只是執(zhí)行棧內(nèi)的同步任務(wù),執(zhí)行完之后會(huì)再次執(zhí)行下一個(gè),直到執(zhí)行完為止,然后棧中無(wú)任務(wù)事件,它就會(huì)等待直到它出現(xiàn),一直這樣的循環(huán)下去
參考文章
JavaScript異步機(jī)制詳解
JavaScript單線程和異步機(jī)制
阮老師Event Loop
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/109873.html
摘要:的單線程,與它的用途有關(guān)。特點(diǎn)的顯著特點(diǎn)異步機(jī)制事件驅(qū)動(dòng)。隊(duì)列的讀取輪詢線程,事件的消費(fèi)者,的主角。它將不同的任務(wù)分配給不同的線程,形成一個(gè)事件循環(huán),以異步的方式將任務(wù)的執(zhí)行結(jié)果返回給引擎。 這兩天跟同事同事討論遇到的一個(gè)問(wèn)題,js中的event loop,引出了chrome與node中運(yùn)行具有setTimeout和Promise的程序時(shí)候執(zhí)行結(jié)果不一樣的問(wèn)題,從而引出了Nodejs的...
摘要:定時(shí)器機(jī)制更正之前的錯(cuò)誤認(rèn)識(shí)函數(shù)內(nèi)調(diào)用,函數(shù)結(jié)束。在規(guī)定的時(shí)間之后,依然會(huì)觸發(fā)的回調(diào)。首先要確認(rèn)幾點(diǎn)單線程瀏覽器多線程單線程原因如果多線程,那么刪除或者創(chuàng)建元素,都需要在線程之間通信。因?yàn)闉g覽器不確定是狀態(tài)。所以,設(shè)計(jì)之初就是單線程。 js定時(shí)器機(jī)制 更正之前的錯(cuò)誤認(rèn)識(shí):1.函數(shù)內(nèi)調(diào)用settimeout,函數(shù)結(jié)束。在規(guī)定的時(shí)間之后,依然會(huì)觸發(fā)settimeout的回調(diào)。 首先要確認(rèn)j...
摘要:每個(gè)線程的任務(wù)執(zhí)行順序都是先進(jìn)先出在運(yùn)行的環(huán)境中,有一個(gè)負(fù)責(zé)程序本身的運(yùn)行,作為主線程另一個(gè)負(fù)責(zé)主線程與其他線程的通信,被稱為線程。主線程繼續(xù)執(zhí)行我是第一主線程執(zhí)行完畢,從線程讀取回調(diào)函數(shù)。 前言 上星期面試被問(wèn)到了事件執(zhí)行順序的問(wèn)題,想起來(lái)之前看《深入淺出Node.js》時(shí)看到這一章就忽略了,這次來(lái)分析一下JavaScript的事件執(zhí)行順序。廢話少說(shuō),正題開始。 單線程JavaScr...
摘要:深入理解引擎的執(zhí)行機(jī)制靈魂三問(wèn)為什么是單線程的為什么需要異步單線程又是如何實(shí)現(xiàn)異步的呢中的中的說(shuō)說(shuō)首先請(qǐng)牢記點(diǎn)是單線程語(yǔ)言的是的執(zhí)行機(jī)制。 深入理解JS引擎的執(zhí)行機(jī)制 1.靈魂三問(wèn) : JS為什么是單線程的? 為什么需要異步? 單線程又是如何實(shí)現(xiàn)異步的呢? 2.JS中的event loop(1) 3.JS中的event loop(2) 4.說(shuō)說(shuō)setTimeout 首先,請(qǐng)牢記2...
摘要:深入理解引擎的執(zhí)行機(jī)制最近在反省,很多知識(shí)都是只會(huì)用,不理解底層的知識(shí)。在閱讀之前,請(qǐng)先記住兩點(diǎn)是單線程語(yǔ)言的是的執(zhí)行機(jī)制。所以,是存在異步執(zhí)行的,比如單線程是怎么實(shí)現(xiàn)異步的場(chǎng)景描述通過(guò)事件循環(huán),所以說(shuō),理解了機(jī)制,也就理解了的執(zhí)行機(jī)制啦。 深入理解js引擎的執(zhí)行機(jī)制 最近在反省,很多知識(shí)都是只會(huì)用,不理解底層的知識(shí)。所以在開發(fā)過(guò)程中遇到一些奇怪的比較難解決的bug,在思考的時(shí)候就會(huì)收...
閱讀 744·2021-11-11 16:54
閱讀 3065·2021-09-26 09:55
閱讀 2015·2021-09-07 10:20
閱讀 1211·2019-08-30 10:58
閱讀 1057·2019-08-28 18:04
閱讀 708·2019-08-26 13:57
閱讀 3598·2019-08-26 13:45
閱讀 1164·2019-08-26 11:42