top

IO與NIO的迷思

版上的版主們大家好 小弟接觸JAVA是新手 也不是讀相關資訊課業的人
第一次接觸的程式語言 就是JAVA  有關JAVA所有的資訊都是來自網路上吸收而來的
也有透過買一些工具書 包括版大的作品(JAVA SE7技術手冊) 來加強一些觀念

初次發文 煩請各位大大們給予指教與教導
(小弟學歷不高 英文不好 對於一些程式用語詞彙其實不是非常精通 但我會努力把我的問題與感想用力的把他解釋清楚)

小弟對於IO與NIO的迷思 一直感到不解..

事情是這樣的 小弟目前有在研究一些開源Project服務端

當我試圖了解透徹其架構的特性時..

目前手中研究的架構是採用IO模型

據我的理解是

IO模型大部分是當一個新連接(client)連接到服務端(server)時

服務端會創建一個執行緒 專門讀取此client的IO事件
當沒有任何可讀的數據或是數據還沒讀完 則此執行緒將會掛起 (即所謂的阻塞狀態?)
等到數據讀完 服務端參考數據之後 服務端就會安排client要做什麼事情或是一些業務的處理..
做完要做的事情之後 再反覆掛起 讀數據..
小型的服務器或許用這樣的架構是不錯 淺顯易懂 理解簡單(至少我能理解XD) 但是當達到大量的連接處理業務時
排山倒海的執行緒 有可能會讓服務器硬體資源吃不消 導致崩潰等等...

所以我在網路上查詢了相關資訊 發現了NIO這玩意

NIO與IO我看起來的差別是 NIO對於所有客戶端的IO事件採取了一個執行緒 來管理處理所有客戶端的IO事件
上面我提到的 IO模型是一個客戶端連接 開一個執行緒 來處理IO事件
NIO模型我理解的是一個執行緒處理所有客戶端的IO事件

但我的疑問來了
如果真的可以用這麼少的資源開銷來管理這麼多client IO事件
那對於client來說 會不會有不順暢的情形發生?
我的理解是 NIO是對每個client做"IO事件"做輪詢 一個一個來處理
如果當前連接有10000個client 當輪詢進度到第5XXX個時
5XXX前面幾個剛好又有IO數據事件來到時 那這樣會不會有處理不順暢的問題產生呢?

IO與NIO迷思具體性的差別除了"資源的消耗"以外  以及"IO事件讀取響應順暢度"的問題
那我們到底該怎麼看這些問題 該怎麼去選擇去處理呢?

也許可以參考一下 Node.js 的應用場合 … 不好的 Node.js 實踐,大概就是不適合 NIO 的場合…

适合使用node.js的场景

TOP

發現你的用詞有誤。正確的用詞才會有準確的討論,準確的討論才可能導出適當的答案。

服務端會創建一個執行緒 專門讀取此client的IO事件
當沒有任何可讀的數據或是數據還沒讀完 則此執行緒將會掛起 (即所謂的阻塞狀態?)
等到數據讀完 服務端參考數據之後 服務端就會安排client要做什麼事情或是一些業務的處理..
做完要做的事情之後 再反覆掛起 讀數據..
小型的服務器或許用這樣的架構是不錯 淺顯易懂 理解簡單(至少我能理解XD) 但是當達到大量的連接處理業務時
排山倒海的執行緒 有可能會讓服務器硬體資源吃不消 導致崩潰等等...

所以我在網路上查詢了相關資訊 發現了NIO這玩意

NIO與IO我看起來的差別是 NIO對於所有客戶端的IO事件採取了一個執行緒 來管理處理所有客戶端的IO事件
上面我提到的 IO模型是一個客戶端連接 開一個執行緒 來處理IO事件
NIO模型我理解的是一個執行緒處理所有客戶端的IO事件


在上這段裡的 IO 與 NIO 其實是二組 API,只是他們各自提供了 Socket 與 non-blocking Socket。
所以,需要用 non-blocking Socket 時,就會用到 NIO 提供的功能。

另外,block 的動作是針對目前你所在的 thread 來說,像寫個簡單的 console application。
它可能只有一個 main thread,如果你寫 GUI application,它會再多出 GUI 相關的 thread。
由上面的描述可以道,我們能因為需要在程式內建出若干 thread。

不管是不是使用 non-blocking Socket,我們都可以將它跑在另一個 thread。
想像一下,你寫了一個 Facebook 桌面版的 app,它有 GUI thread 與程式本身的 main thread。
GUI 上也許有不同的 TAB,使用者按了『最新動態』TAB,覺得很久沒回應,想按『塗鴨牆』但程式不理他。
一整個像當掉一樣。

我們可以合理猜測:要透過網路連線的部分『佔用』GUI thread,
所以 GUI 沒有時間理會使用者要切換 TAB 的要求。
這也是為什麼製作 GUI 的課程內,常會明確表示 GUI thread 內不要有非 GUI 操作的動作,這些動作應該放在不同的 thread。
例如:網路連線。實作上,就是由 GUI thread 開一個新的 thread,它會做網路資料讀取。


但我的疑問來了
如果真的可以用這麼少的資源開銷來管理這麼多client IO事件
那對於client來說 會不會有不順暢的情形發生?
我的理解是 NIO是對每個client做"IO事件"做輪詢 一個一個來處理
如果當前連接有10000個client 當輪詢進度到第5XXX個時
5XXX前面幾個剛好又有IO數據事件來到時 那這樣會不會有處理不順暢的問題產生呢?

IO與NIO迷思具體性的差別除了"資源的消耗"以外  以及"IO事件讀取響應順暢度"的問題
那我們到底該怎麼看這些問題 該怎麼去選擇去處理呢?


現在你的認知是:使用 non-blocking Socket 只能配合一個 thread。
你應該想成使用 non-blocking Socket 有機會讓你選擇只用一個 thread,是不是要開更多 thread 可以看使用量來決定。

若是使用 blocking Socket,為了不讓目前的 thread 停止動作(例如:GUI application)
你必需將 Socket 的讀寫放到不同的 thread 上,它至少要 1 個 client (或一組 Socket)開一個 thread。

一個是有選擇,一個是沒選擇(或接受程式沒有回應)。

TOP

也許也可以參考一下這篇:
http://www.codedata.com.tw/java/ ... 9-listenablefuture/
  1. readFile(args[0],
  2.     content -> out.println(content),  // success
  3.     ex -> ex.printStackTrace(),       // error
  4.     Executors.newFixedThreadPool(10)
  5. );
複製程式碼
這模擬  Node.js 的風格來讀取一個文字檔案,當數字不設為 1 時,是這段引言的情境之一:
你應該想成使用 non-blocking Socket 有機會讓你選擇只用一個 thread,是不是要開更多 thread 可以看使用量來決定。

TOP