2013-06-04 74 views
3

我一直在閱讀和經歷儘可能多的NodeJs代碼,但我對此有點困惑:NodeJs中單線程和非阻塞I/O操作有什麼區別?

究竟Node是單線程的意思,什麼是非阻塞I/O意思?我可以通過產生子進程來實現第一個,使用異步庫實現第二個進程。但我想澄清它是什麼意思,以及非阻塞I/O如何仍然可以減慢你的應用程序。

+2

我發現這個鏈接是得心應手:http://blog.mixu.net/2011/02/01/understanding-the -node-js-event-loop/ –

+1

也很有用:http://ejohn.org/blog/how-javascript-timers-work/ –

回答

8

我會盡我所能解釋。

單線程意味着Node.js Javascript運行時 - 在特定的時間點 - 只執行其加載的所有代碼中的一段代碼。實際上,它從某個地方開始,並通過所有指令(調用堆棧)完成,直到完成。在執行代碼時,沒有什麼可以中斷這個過程,所有的I/O都必須等待。值得慶幸的是,大多數調用堆棧都比較短,我們在Node.js中做的很多事情都比「CPU」更重要的是「簿記」類型。

儘管單線程,任何需要很長時間的指令都會成爲系統響應的一個巨大問題。運行時一次只能做一件事,所以一切都必須等到該指令完成。如果任何「I/O」指令(例如從磁盤讀取)都會阻止執行,那麼系統在那個時候將不必要地不可用。

但謝天謝地,我們有非阻塞的I/O。

而不是等待一個文件來讀:

console.log(readFileSync(filePath))

你寫你的代碼,這樣你不等待讀取的文件:

readFile(filePath)

readFile調用幾乎立即返回(可能在幾納秒內),因此運行時可以繼續執行接下來的指令。但是,如果readFile調用在數據讀取之前返回,那麼readFile調用就無法返回文件內容。這就是回調進來:

readFile(filePath, function(err, contents) { console.log(contents))

儘管如此,readFile調用返回幾乎瞬間。運行時可以繼續。它將在它之前完成當前工作(所有指令都在readFile之後)。除了存儲對它的引用外,沒有任何事情是通過傳遞的函數完成的。

然後,在稍後的某個時間點(可能是10ms,100ms或1000ms以後)讀完文件時,將使用第二個參數調用該文件的全部內容。在此之前,運行時可以完成任何其他批次的工作。

現在我將闡述您對有關產卵子進程和異步庫的評論。這兩個帳戶都是錯誤的。

  • 產生子進程是一種讓Node.js使用多於CPU內核的方法。單線程,單個Node.js沒有使用多個內核的目的。不過,如果您使用的是多核計算機,則可能需要使用所有這些核心。因此,啓動多個Node.js.流程。

  • 異步庫不會給你非阻塞的I/O,Node.js會給你。什麼Node.js不給你自己,是一個簡單的方法來處理來自多個回調的數據。異步庫可以幫助很多。

由於我不是Node.js內部專家,我歡迎更正!

相關問題:

+0

優秀的答案,我顯然在很多方面都是錯誤的。那麼你如何看待處理CPU密集型任務?就像說,我有一個應用程序可以同步來自不同網站的信息。同步可以作爲後臺進程以定期輪詢的方式進行。你不會建議使用產生的過程嗎? – Hick

+0

當然不是。由於輪詢是週期性的,並且每次輪詢後需要完成的實際工作(即計算)可能很小,因此對於單個Node.js流程來說,這是一個很好的用例。使用多個進程的唯一原因是如果您希望能夠使多個內核飽和。 –

+0

我的構建輪詢的想法是編寫一個獨立的看門狗類庫,它運行在一個單獨的線程上,並且不停地輪詢和更新數據庫,而不會打擾事件循環/用戶請求。 – Hick

相關問題