亚洲最大看欧美片,亚洲图揄拍自拍另类图片,欧美精品v国产精品v呦,日本在线精品视频免费

  • 站長資訊網(wǎng)
    最全最豐富的資訊網(wǎng)站

    JavaScript的單線程你真的理解了嗎

    本篇文章給大家?guī)砹宋覀兊腏avaScript單線程的相關(guān)知識,JavaScript是一門單線程的語言,為什么JavaScript可以一邊執(zhí)行定時器一邊執(zhí)行函數(shù),希望對大家有幫助。

    JavaScript的單線程你真的理解了嗎

    1. 進(jìn)程與線程

    1.1 進(jìn)程(Process)

    是計算機中的程序關(guān)于某數(shù)據(jù)集合上的一次運行活動,是系統(tǒng)進(jìn)行資源分配和調(diào)度的基本單位,是操作系統(tǒng)結(jié)構(gòu)的基礎(chǔ)。 在當(dāng)代面向線程設(shè)計的計算機結(jié)構(gòu)中,進(jìn)程是線程的容器。程序是指令、數(shù)據(jù)及其組織形式的描述,進(jìn)程是程序的實體。是計算機中的程序關(guān)于某數(shù)據(jù)集合上的一次運行活動,是系統(tǒng)進(jìn)行資源分配和調(diào)度的基本單位,是操作系統(tǒng)結(jié)構(gòu)的基礎(chǔ)。程序是指令、數(shù)據(jù)及其組織形式的描述,進(jìn)程是程序的實體。

    我們這里將進(jìn)程比喻為工廠的車間,它代表CPU所能處理的單個任務(wù)。任一時刻,CPU總是運行一個進(jìn)程,其他進(jìn)程處于非運行狀態(tài)。

    1.2 線程(thread)

    是操作系統(tǒng)能夠進(jìn)行運算調(diào)度的最小單位。它被包含在進(jìn)程之中,是進(jìn)程中的實際運作單位。一條線程指的是進(jìn)程中一個單一順序的控制流,一個進(jìn)程中可以并發(fā)多個線程,每條線程并行執(zhí)行不同的任務(wù)。

    這里把線程比喻一個車間的工人,即一個車間可以允許由多個工人協(xié)同完成一個任務(wù)。

    2. 多線程的瀏覽器

    瀏覽器內(nèi)核是多線程,在內(nèi)核控制下各線程相互配合以保持同步,一個瀏覽器通常由以下常駐線程組成:

    • GUI 渲染線程

    • JavaScript引擎線程

    • 事件觸發(fā)線程

    • 定時觸發(fā)器線程

    • 異步http請求線程

    JavaScript的單線程你真的理解了嗎

    我們看到了JS引擎線程,非常的熟悉,沒有錯,這里是我們執(zhí)行javascript腳本程序的地方。

    而JS引擎是多線程的,單線程是指JS引擎執(zhí)行JS時只分了一個線程給他執(zhí)行,意思是JS引擎分配了一個線程給JavaScript執(zhí)行,也就是我們所說的單線程。

    2.1 這里再說下JS的執(zhí)行機制

    由于JavaScript是單線程(一個Tab頁內(nèi)中無論什么時候都只有一個JS線程在運行JavaScript程序)。

    所以我們需要依靠任務(wù)隊列來進(jìn)行JavaScript代碼的執(zhí)行。

    JS引擎會一直等待著任務(wù)隊列中任務(wù)的到來,然后執(zhí)行任務(wù)。

    同步任務(wù)這么執(zhí)行當(dāng)然沒問題,我們把任務(wù)都放在任務(wù)隊列里,一個一個執(zhí)行,邏輯很清晰。但是,如果我們向后臺發(fā)送請求,發(fā)送加接收這段時間可能需要一秒,我們不能等它一秒吧,如果請求五次,那就等五秒?顯示不符合我們的需求,所以,我們需要異步任務(wù)來處理這個問題。

    2.2 同步任務(wù)和異步任務(wù)

    同步任務(wù)是指在主線程上排隊執(zhí)行的任務(wù),只有前一個任務(wù)執(zhí)行完畢,才能繼續(xù)執(zhí)行下一個任務(wù),當(dāng)我們打開網(wǎng)站時,網(wǎng)站的渲染過程,比如元素的渲染,其實就是一個同步任務(wù)

    異步任務(wù)是指不進(jìn)入主線程,而進(jìn)入任務(wù)隊列的任務(wù),只有任務(wù)隊列通知主線程,某個異步任務(wù)可以執(zhí)行了,該任務(wù)才會進(jìn)入主線程,當(dāng)我們打開網(wǎng)站時,像圖片的加載,音樂的加載,其實就是一個異步任務(wù)。

    大家肯定對Event Loop有比較具象的認(rèn)知,這邊我不詳細(xì)說了,不懂可以和我說,我再講就是了。

    3. 本文重重點–可直接看

    但是,大家有沒有對任務(wù)隊列抱有疑問?這是個對象?是個數(shù)組?按我的邏輯來說,我們JavaScript主線程執(zhí)行同步函數(shù),異步函數(shù)可以放在任務(wù)隊列里,這個任務(wù)隊列可以是個對象,當(dāng)我們執(zhí)行完同步任務(wù)的時候,把這個對象(任務(wù)隊列)壓進(jìn)主線程中就可以了,但是事實并不我想的這樣的。

    Evnet Loop的任務(wù)隊列放在了瀏覽器的事件觸發(fā)線程中,當(dāng)JS引擎執(zhí)行異步函數(shù)的時候,會將異步任務(wù)放在事件觸發(fā)線程中,當(dāng)對應(yīng)的異步任務(wù)符合觸發(fā)條件被觸發(fā)時,事件觸發(fā)線程會把異步任務(wù)添加到JS引擎中的主線程的隊尾,等待執(zhí)行。

    是不是和我們想象的JavaScript單線程不太一樣?好吧,確實不太一樣,所以最后的結(jié)論是,我們所說的任務(wù)隊列竟然是一個線程。

    然后,說回我們開頭剛開始說過的定時器,大家基本也能猜出來了,它是由定時器線程控制的。

    因為JavaScript是單線程的, 如果處于阻塞線程狀態(tài)就會影響記計時的準(zhǔn)確,因此很有必要單獨開一個線程用來計時。

    當(dāng)使用setTimeout或setInterval時,它需要定時器線程計時,計時完成后就會將特定的事件推入事件隊列中。

    4. 結(jié)論

    所以說,我們說JavaScript是單線程的沒錯,就是天王老子來了它也是單線程的,但是我們的Event Loop和定時器是放在其他線程中的。

    5. V8引擎–擴展

    V8引擎是一個JavaScript引擎實現(xiàn),最初由一些語言方面專家設(shè)計,后被谷歌收購,隨后谷歌對其進(jìn)行了開源。

    V8使用C++開發(fā),在運行JavaScript之前,相比其它的JavaScript的引擎轉(zhuǎn)換成字節(jié)碼或解釋執(zhí)行,V8將其編譯成原生機器碼(IA-32, x86-64, ARM, or MIPS CPUs),并且使用了如內(nèi)聯(lián)緩存(inline caching)等方法來提高性能。

    有了這些功能,JavaScript程序在V8引擎下的運行速度媲美二進(jìn)制程序。V8支持眾多操作系統(tǒng),如windows、linux、android等,也支持其他硬件架構(gòu),如IA32,X64,ARM等,具有很好的可移植和跨平臺特性。

    5.1 工作流程

    V8引擎在執(zhí)行JavaScript的過程中,主要有兩個階段:編譯和運行,與C++的執(zhí)行前完全編譯不同的是,JavaScript需要在用戶使用時完成編譯和執(zhí)行。在V8中,JavaScript相關(guān)代碼并非一下完成編譯的,而是在某些代碼需要執(zhí)行時,才會進(jìn)行編譯,這就提高了響應(yīng)時間,減少了時間開銷。在V8引擎中,源代碼先被解析器轉(zhuǎn)變?yōu)槌橄笳Z法樹(AST),然后使用JIT編譯器的全代碼生成器從AST直接生成本地可執(zhí)行代碼。這個過程不同于JAVA先生成字節(jié)碼或中間表示,減少了AST到字節(jié)碼的轉(zhuǎn)換時間,提高了代碼的執(zhí)行速度。但由于缺少了轉(zhuǎn)換為字節(jié)碼這一中間過程,也就減少了優(yōu)化代碼的機會。

    V8引擎編譯本地代碼時使用的主要類如下所示:

    • Script:表示JavaScript代碼,即包含源代碼,又包含編譯之后生成的本地代碼,即是編譯入口,又是運行入口;

    • Compiler:編譯器類,輔組Script類來編譯生成代碼,調(diào)用解釋器(Parser)來生成AST和全代碼生成器,將AST轉(zhuǎn)變?yōu)楸镜卮a;

    • AstNode:抽象語法樹節(jié)點類,是其他所有節(jié)點的基類,包含非常多的子類,后面會針對不同的子類生成不同的本地代碼;

    • AstVisitor:抽象語法樹的訪問者類,主要用來遍歷異構(gòu)的抽象語法樹;

    • FullCodeGenerator:AstVisitor類的子類,通過遍歷AST來為JavaScript生成本地可執(zhí)行代碼。

    JavaScript的單線程你真的理解了嗎

    JavaScript代碼編譯的過程大致為:Script類調(diào)用Compiler類的Compile函數(shù)為其生成本地代碼。Compile函數(shù)先使用Parser類生成AST,再使用FullCodeGenerator類來生成本地代碼。本地代碼與具體的硬件平臺密切相關(guān),F(xiàn)ullCodeGenerator使用多個后端來生成與平臺相匹配的本地匯編代碼。由于FullCodeGenerator通過遍歷AST來為每個節(jié)點生成相應(yīng)的匯編代碼,缺失了全局視圖,節(jié)點之間的優(yōu)化也就無從談起

    贊(0)
    分享到: 更多 (0)
    網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號