javascript:多線程與僞線程

web worker

這裏就很少說了,主要說僞線程。由於web worker不能操做dom元素,不少時候用不上。javascript

僞線程

重點:
瀏覽器的內核是多線程的,一個瀏覽器通常至少實現三個常駐線程:javascript引擎線程,GUI渲染線程,瀏覽器事件觸發線程。java

a.javascript引擎是基於事件驅動單線程執行的,JS引擎一直等待着任務隊列中任務的到來,而後加以處理,瀏覽器不管何時都只有一個JS線程在運行JS程序。
b.GUI渲染線程負責渲染瀏覽器界面,當界面須要重排、重繪或因爲某種操做引起迴流時,該線程就會執行。但須要注意 GUI渲染線程與JS引擎是互斥的,當JS引擎執行時GUI線程會被掛起,GUI更新會被保存在一個隊列中等到JS引擎空閒時當即被執行。
c.事件觸發線程,當一個事件被觸發時該線程會把事件添加到待處理隊列的隊尾,等待JS引擎的處理。這些事件可來自JavaScript引擎當前執行的代碼塊如setTimeOut、也可來自瀏覽器內核的其餘線程如鼠標點擊、AJAX異步請求等,但因爲JS的單線程關係全部這些事件都得排隊等待JS引擎處理。web

當咱們要循環過百萬級的數據甚至億的時候怎麼辦?
那就用setTimeout模擬一個多線程。
重點:js的工做機制是:當線程中沒有執行任何同步代碼的前提下才會執行異步代碼,setTimeout是異步代碼,因此setTimeout只能等js空閒纔會執行,但死循環是永遠不會空閒的,因此setTimeout也永遠不會執行。即便setTimeout爲0,他也是等js引擎的代碼執行完以後纔會插入到js引擎線程的最後執行。
上栗子數組

var thread = function () {
    var nowTime = 0, //線程已經執行了多久
        maxTime = 15;//線程最多執行多久
    var threadArr = [];//數組模擬線程隊列
    
    this.addThread = function (fn) {
        threadArr.push(fn)
    }
    this.start=function () {
        doingThread();
    }
    var doingThread = function () {
        if (threadArr.length > 0) {
            if (nowTime < maxTime) {
                let now = new Date().getTime();
                var method = threadArr[0];
                method();
                threadArr.splice(0, 1);
                let nowNew = (new Date().getTime() - now);
                nowTime += nowNew;
                doingThread();
            } else {//每執行完線程後睡1ms
                nowTime=0;
                setTimeout(doingThread, 1);
            }
        }else {//先睡着等待線程隊列
            setTimeout(doingThread,100)
        }
    }
}
var fn = function (num) {
    console.log(num)
}

var thread = new thread();
thread.start()
for (let i = 0; i < 1000000; i++) {
    thread.addThread(function () {
        fn(i)
    })
}

clipboard.png

循環百萬級的數據量而且不阻塞Ui線程是徹底沒問題的,但過億瀏覽器仍是會蹦。(這裏只是提供個簡單的思路,其實過億也能夠不蹦)瀏覽器

相關文章
相關標籤/搜索