瀏覽器內核常駐線程

瀏覽器內核常駐線程

  1. 瀏覽器 GUI 渲染線程
  2. JavaScript 引擎線程
  3. 瀏覽器定時觸發器線程
  4. 瀏覽器事件觸發線程 
  5. 瀏覽器 http 異步請求線程

瀏覽器 GUI 渲染線程 和 JavaScript 引擎線程之間是互斥的

在debug裏面check一下以下代碼的效果便可知道html

var sleep = function(time) {
    var date = new Date(); 
    while(new Date() - date <= time) {}
}
document.body.innerHTML = '123';
sleep(3000)

 

原理也很簡單:瀏覽器

  • GUI渲染線程負責渲染瀏覽器界面的HTML元素, 當界面須要重繪(repaint)因爲某種操做引起迴流(reflow)時,該線程就會執行。
  • 由於 JavaScript腳本是可操縱DOM元素, 在修改這些元素屬性同時渲染界面, 那麼渲染線程先後得到的元素數據就可能不一致了。
  • 因此在腳本中執行對界面進行更新操做, 如添加結點,刪除結點或改變結點的外觀等更新並不會當即體現出來, 這些操做將保存在一個隊列中,待JavaScript引擎空閒時纔有機會渲染出來。

因此當遇到在js引擎運算量較大的時候, 又想及時調用GUI渲染,能夠作以下修改:併發

var sleep = function(time) {
    var date = new Date(); 
    while(new Date() - date <= time) {}
}
document.body.innerHTML = '123';
setTimeout(function() {
   sleep(3000);
}, 0);

 

JavaScript 引擎線程

事件驅動(event driven)機制

事件驅動通常經過事件循環(event loop)和事件隊列(event queue)來實現的。app

假定瀏覽器中有一個專門用於事件調度的實例(該實例能夠是一個線程,能夠稱之爲事件分發線程event dispatch thread),該實例的工做就是一個不結束的循環,從事件隊列中取出事件,處理全部很事件關聯的回調函數(event handler)。異步

注意回調函數是在Javascript的主線程中運行的,而非事件分發線程中,以保證事件處理不會發生阻塞。  函數

Event loop codeoop

 

若是隊列非空,引擎就從隊列頭取出一個任務,直到該任務處理完,即返回後引擎接着運行下一個任務, 在任務沒返回前隊列中的其它任務是無法被執行的.spa

與其它線程間的通訊

  

瀏覽器 http 異步請求線程

瀏覽器對同一域名進行請求的併發鏈接數是有限制的,result10 in IE 8, 6 in Firefox 3+ and Chrome 5+。詳情參考demo: http://developer.oncecode.com/comet/線程

XMLHttpRequest在鏈接後是經過瀏覽器新開一個線程請求, 將檢測到狀態變動時,若是設置有回調函數,異步線程就產生狀態變動事件放到 JavaScript引擎的處理隊列中等待處理debug

 

瀏覽器事件觸發線程 

接受瀏覽器裏面的操做事件響應。如在監聽到鼠標、鍵盤等事件的時候, 若是有事件句柄函數,就講對應的任務壓入隊列。

 

瀏覽器定時觸發線程

瀏覽器模型定時計數器並非由JavaScript引擎計數的, 由於JavaScript引擎是單線程的, 若是處於阻塞線程狀態就會影響記計時的準確, 它必須依賴外部來計時並觸發定時。

setTimeout & setInterval

setTimeout:在參數指定的時間後將待執行方法放到執行隊列中, 若是隊列中沒有其餘方法等待,則會當即執行setTimeout指定的方法。
setIinterVal:  定時觸發器線程每間隔指定的時間將指定方法放入到執行隊列中,  當函數執行時,若是發現同一個定時器已經有多個在等待執行的任務,只會執行1次。後面的會被忽略掉。 
 
var sleep = function(time) {
    var date = new Date(); 
    while(new Date() - date <= time) {}
}
var time = new Date();
var a = setInterval(function(){
    sleep(200);
    console.log(new Date() - time);
    if(new Date() - time > 700) clearInterval(a);
}, 100);
  
//output 
303
506
708

 

以上代碼表示在700時間內,一共有7個timer callback被壓入隊尾, clearInterval後, 只有3個timer對應的callback獲得執行。 因此這種狀況能夠採用setTimeout的方式來讓執行結果更加符合開發預期:

var a = setTimeout(function(){
    sleep(200);
    setTimeout(arguments.callee, 100)
}, 100);

 

轉自:http://www.cnblogs.com/mininice/p/4298952.html

相關文章
相關標籤/搜索