11_javascript線程機制與事件機制

進程與線程

進程:
程序的一次執行, 它佔有一片獨有的內存空間
可以通過windows任務管理器查看進程
線程:
是進程內的一個獨立執行單元
是程序執行的一個完整流程
是CPU的最小的調度單元

在這裏插入圖片描述

進程與線程
* 一個進程中一般至少有一個運行的線程: 主線程
* 一個進程中也可以同時運行多個線程, 我們會說程序是多線程運行的
* 一個進程內的數據可以供其中的多個線程直接共享
* 多個進程之間的數據是不能直接共享的
瀏覽器運行是單進程還是多進程?
有的是單進程
	* firefox
	* 老版IE

有的是多進程
	* chrome
	* 新版IE
如何查看瀏覽器是否是多進程運行的呢?
  • 任務管理器==>進程
瀏覽器運行是單線程還是多線程?
  • 都是多線程運行的
相關問題

1.何爲多進程與多線程?

多進程運行: 應用程序可以同時啓動多個實例運行
多線程: 在一個進程內, 同時有多個線程運行

2.比較單線程與多線程?

多線程:
	優點:
		能有效提升CPU的利用率
	缺點:
		創建多線程開銷
		線程間切換開銷
		死鎖與狀態同步問題

單線程:
	優點:
		順序編程簡單易懂
	缺點:
		效率低

3.JS是單線程還是多線程?

js是單線程運行的
但使用H5中的 Web Workers可以多線程運行

瀏覽器內核

什麼是瀏覽器內核?
支持瀏覽器運行的最核心的程序

不同的瀏覽器可能不太一樣
	* Chrome, Safari: webkit
	* firefox: Gecko
	* IE: Trident
	* 360,搜狗等國內瀏覽器: Trident + webkit

內核由很多模塊組成
	* html,css文檔解析模塊 : 負責頁面文本的解析
	* dom/css模塊 : 負責dom/css在內存中的相關處理
	* 佈局和渲染模塊 : 負責頁面的佈局和效果的繪製
	* 定時器模塊 : 負責定時器的管理
	* 網絡請求模塊 : 負責服務器請求(常規/Ajax)
	* 事件響應模塊 : 負責事件的管理

定時器引發的思考

定時器真是定時執行的嗎?
  • 定時器並不能保證真正定時執行
  • 一般會延遲一丁點(可以接受), 也有可能延遲很長時間(不能接受)
定時器回調函數是在分線程執行的嗎?
  • 在主線程執行的, js是單線程的
定時器是如何實現的?

事件循環模型

document.getElementById('btn').onclick = function () {
	var start = Date.now()
	console.log('啓動定時器前...')
	setTimeout(function () {
		console.log('定時器執行了', Date.now()-start)
	}, 200)
	console.log('啓動定時器後...')
}

JS是單線程的

如何證明js執行是單線程的?
  • setTimeout()的回調函數是在主線程執行的
  • 定時器回調函數只有在運行棧中的代碼全部執行完後纔有可能執行
爲什麼js要用單線程模式, 而不用多線程模式?
  • JavaScript的單線程,與它的用途有關。
  • 作爲瀏覽器腳本語言,JavaScript的主要用途是與用戶互動,以及操作DOM。
  • 這決定了它只能是單線程,否則會帶來很複雜的同步問題

代碼的分類:

  • 初始化代碼
  • 回調代碼
js引擎執行代碼的基本流程
先執行初始化代碼: 包含一些特別的代碼   
	* 回調函數(異步執行)
	* 設置定時器
	* 綁定事件監聽
	* 發送ajax請求
後面在某個時刻纔會執行回調代碼

事件循環模型

所有代碼分類
初始化執行代碼(同步代碼): 包含綁定dom事件監聽, 設置定時器, 發送ajax請求的代碼
回調執行代碼(異步代碼): 處理回調邏輯
js引擎執行代碼的基本流程:

初始化代碼===>回調代碼

模型的2個重要組成部分:
  • 事件(定時器/DOM事件/Ajax)管理模塊
  • 回調隊列
模型的運轉流程
  • 執行初始化代碼, 將事件回調函數交給對應模塊管理
  • 當事件發生時, 管理模塊會將回調函數及其數據添加到回調列隊中
  • 只有當初始化代碼執行完後(可能要一定時間), 纔會遍歷讀取回調隊列中的回調函數執行

在這裏插入圖片描述

Web Workers
  1. H5規範提供了js分線程的實現, 取名爲: Web Workers
  2. 相關API
  • Worker: 構造函數, 加載分線程執行的js文件
  • Worker.prototype.onmessage: 用於接收另一個線程的回調函數
  • Worker.prototype.postMessage: 向另一個線程發送消息
  1. 不足
  • worker內代碼不能操作DOM(更新UI)
  • 不能跨域加載JS
  • 不是每個瀏覽器都支持這個新特性

內存溢出與內存泄露

內存溢出
  • 一種程序運行出現的錯誤
  • 當程序運行需要的內存超過了剩餘的內存時, 就出拋出內存溢出的錯誤
內存泄露
  • 佔用的內存沒有及時釋放
  • 內存泄露積累多了就容易導致內存溢出
  • 常見的內存泄露:
    • 意外的全局變量
    • 沒有及時清理的計時器或回調函數
    • 閉包
// 1. 內存溢出
var obj = {}
for (var i = 0; i < 10000; i++) {
	obj[i] = new Array(10000000)
	console.log('-----')
}
 
// 2. 內存泄露
// 意外的全局變量
function fn() {
	a = new Array(10000000)
	console.log(a)
}
fn()
 
// 沒有及時清理的計時器或回調函數
var intervalId = setInterval(function () { //啓動循環定時器後不清理
	console.log('----')
}, 1000)
// clearInterval(intervalId)
 
// 閉包
function fn1() {
	var a = 4
	function fn2() {
		console.log(++a)
	}
	return fn2
}
var f = fn1()
f()
// f = null
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章