1.行程與執行緒
什么是行程?
我們可以在電腦的任務管理器中查看到正在運行的行程,可以認為一個行程就是在運行一個程式,比如用瀏覽器打開一個網頁,這就是開啟了一個行程,但是比如打開3個網頁,那么就開啟了3個行程,我們這里只研究打開一個網頁即一個行程,
一個行程的運行,當然需要很多個執行緒互相配合,比如打開QQ的這個行程,可能同時有接收訊息執行緒、傳輸檔案執行緒、檢測安全執行緒…所以一個網頁能夠正常的運行并和用戶互動,也需要很多個行程之間相互配合!
總結:最重要的是一個行程中可能有多個執行不同任務的執行緒
帶著我的總結去理解下面的的話!!!
2.瀏覽器當中的執行緒
js在設計之初就設計為單執行緒的即js主執行緒,即js的代碼只能在一個執行緒上運行,也就說,js同時只能執行一個js任務
那么諸如onclick回呼,setTimeout,Ajax這些都是怎么實作的呢?
這些屬于不同的執行緒我只有主執行緒執行js代碼,按照道理我并不能執行這些代碼呀!
這是因為瀏覽器或者node(宿主環境)是多執行緒的即瀏覽器多設定了幾個執行緒去輔助js執行緒的運行
瀏覽器有很多執行緒:
1.js引擎執行緒(js引擎有多個執行緒,一個主執行緒,其它的后臺配合主執行緒)
作用:執行js任務(執行js代碼,用戶輸入,網路請求)
2.ui渲染執行緒
作用:渲染頁面(js可以操作dom,影響渲染,所以js引擎執行緒和UI執行緒是互斥的,js執行時會阻塞頁面的渲染,)
3.事件輪詢處理執行緒
作用:輪詢訊息佇列,event loop
4.其他執行緒,
有 定時器觸發執行緒 (setTimeout)、http 異步執行緒、瀏覽器事件執行緒 (onclick)等等,
所以異步是瀏覽器的兩個或者兩個以上執行緒共同完成的,比如ajax異步請求和setTimeout
我下面講講這些執行緒 ,能幫助你理解瀏覽器當中的代碼到底是怎樣運行的!
3.js引擎執行緒
js引擎執行緒,我們稱為主執行緒,他就是我們常說的“單執行緒”,即運行js代碼的那個執行緒(不包括異步代碼!!!)
1 var dlz = 2;
2 setTimeout()
3 ajax()
4 console.log()
第1、4行代碼是同步代碼,直接在主執行緒中運行;第2、3行代碼交給其他執行緒運行,
具體運行順序與堆疊和執行背景關系有關這里就不過多解釋,理解剛才說的就行,
4.其他執行緒
理解其他執行緒之前我們先理解一下任務佇列(訊息佇列),任務佇列是一個佇列它存盤的是一堆異步成功后的回呼函式字串,肯定是先成功的異步的回呼函式在佇列的前面,后成功的在后面,
劃重點:是相應的執行緒執行成功之后的代碼即回呼函式放入任務佇列里面,而不是直接放在任務佇列里面!!!這點可能顛覆了很多人的認知
比如setTimeout 2秒后執行一個函式,那么這個函式是在2秒后才進佇列的,
定時器觸發執行緒 (setTimeout)、http 異步執行緒、瀏覽器事件執行緒 (onclick)
主執行緒執行JS代碼時,碰到異步代碼,就把它交給各自相對應的執行緒去執行,比如:
1 var a = 2;
2 setTimeout(fun A)
3 ajax(fun B)
4 console.log()
5 dom.onclick(func C)
主執行緒在運行這段代碼時,碰到2 setTimeout(fun A),把這行代碼交給定時器觸發執行緒去執行
碰到3 ajax(fun B),把這行代碼交給http 異步執行緒去執行
碰到5 dom.onclick(func C) ,把這行代碼交給瀏覽器事件執行緒去執行
注意: 這幾個異步代碼的回呼函式fun A,fun B,fun C,各自的執行緒都會保存著的,因為需要在未來的某個時候,將回呼函式交給主執行緒去執行
是不是瞬間理解了我們為啥要寫回呼函式!!!
總結:這些執行緒主要有兩個作用:
1.執行相對應的代碼
2.保存回呼函式,在未來的某個時刻,通知EventLoop輪詢處理執行緒(下面會講)過來取相應的回呼函式然后執行
5.EventLoop輪詢處理執行緒
上面我們已經知道了,有3個東西
主執行緒,處理同步代碼
幾個異步執行緒,處理異步代碼
訊息佇列,存盤著異步成功后的回呼函式,一個靜態存盤結構
這里再對訊息佇列其作用就是存放著未來要執行的回呼函式,比如
setTimeout(() => {
console.log(222)
}, 2000)
setTimeout(() => {
console.log(333)
}, 3000)
在一開始,訊息佇列是空的,在2秒后,一個 () => {
console.log(222)
} 的函式進入佇列,在3秒后,一個 () => {
console.log(333)
}的函式進入佇列,此時佇列里有兩個元素,主執行緒從佇列頭中挨個取出并執行,
但是新的問題又來了,我主執行緒怎么知道任務佇列里面是否有需要執行的回呼函數呢?
此時需要用到我們的EventLoop輪詢處理執行緒
它會在執行完同步任務之后會不斷的向任務佇列里面詢問:“啊,你這里有沒有要我執行的任務呀?”
有的話根據先進先出來執行!
6.總結
通過我上面的講解大概能理解瀏覽器的運行機制,順帶理解了為什么我們經常寫代碼要寫回呼函式這個問題(先運行異步任務之后里面的回呼函式交給瀏覽器主執行緒去執行)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/377102.html
標籤:其他
