1. 程式人生 > >Java NIO 與 IO

Java NIO 與 IO

作者:Jakob Jenkov   譯者:郭蕾    校對:方騰飛

當學習了Java NIO和IO的API後,一個問題馬上湧入腦海:

我應該何時使用IO,何時使用NIO呢?在本文中,我會盡量清晰地解析Java NIO和IO的差異、它們的使用場景,以及它們如何影響您的程式碼設計。

Java NIO和IO的主要區別

下表總結了Java NIO和IO之間的主要差別,我會更詳細地描述表中每部分的差異。

IO                NIO
面向流            面向緩衝
阻塞IO            非阻塞IO
無                選擇器

面向流與面向緩衝

Java NIO和IO之間第一個最大的區別是,IO是面向流的,NIO是面向緩衝區的。 Java IO面向流意味著每次從流中讀一個或多個位元組,直至讀取所有位元組,它們沒有被快取在任何地方。此外,它不能前後移動流中的資料。如果需要前後移動從流中讀取的資料,需要先將它快取到一個緩衝區。 Java NIO的緩衝導向方法略有不同。資料讀取到一個它稍後處理的緩衝區,需要時可在緩衝區中前後移動。這就增加了處理過程中的靈活性。但是,還需要檢查是否該緩衝區中包含所有您需要處理的資料。而且,需確保當更多的資料讀入緩衝區時,不要覆蓋緩衝區裡尚未處理的資料。

阻塞與非阻塞IO

Java IO的各種流是阻塞的。這意味著,當一個執行緒呼叫read() 或 write()時,該執行緒被阻塞,直到有一些資料被讀取,或資料完全寫入。該執行緒在此期間不能再幹任何事情了。 Java NIO的非阻塞模式,使一個執行緒從某通道傳送請求讀取資料,但是它僅能得到目前可用的資料,如果目前沒有資料可用時,就什麼都不會獲取。而不是保持執行緒阻塞,所以直至資料變的可以讀取之前,該執行緒可以繼續做其他的事情。 非阻塞寫也是如此。一個執行緒請求寫入一些資料到某通道,但不需要等待它完全寫入,這個執行緒同時可以去做別的事情。 執行緒通常將非阻塞IO的空閒時間用於在其它通道上執行IO操作,所以一個單獨的執行緒現在可以管理多個輸入和輸出通道(channel)。

選擇器(Selectors

Java NIO的選擇器允許一個單獨的執行緒來監視多個輸入通道,你可以註冊多個通道使用一個選擇器,然後使用一個單獨的執行緒來“選擇”通道:這些通道里已經有可以處理的輸入,或者選擇已準備寫入的通道。這種選擇機制,使得一個單獨的執行緒很容易來管理多個通道。

NIO和IO如何影響應用程式的設計

無論您選擇IO或NIO工具箱,可能會影響您應用程式設計的以下幾個方面:

  1.  對NIO或IO類的API呼叫。
  2. 資料處理。
  3. 用來處理資料的執行緒數。

API呼叫

當然,使用NIO的API呼叫時看起來與使用IO時有所不同,但這並不意外,因為並不是僅從一個InputStream逐位元組讀取,而是資料必須先讀入緩衝區再處理。

資料處理

使用純粹的NIO設計相較IO設計,資料處理也受到影響。

在IO設計中,我們從InputStream或 Reader逐位元組讀取資料。假設你正在處理一基於行的文字資料流,例如:

Name: Anna
Age: 25
Email: [email protected]
Phone: 1234567890

該文字行的流可以這樣處理:
InputStream input = … ; // get the InputStream from the client socket

BufferedReader reader = new BufferedReader(new InputStreamReader(input));

String nameLine   = reader.readLine();
String ageLine    = reader.readLine();
String emailLine  = reader.readLine();
String phoneLine  = reader.readLine();

請注意處理狀態由程式執行多久決定。換句話說,一旦reader.readLine()方法返回,你就知道肯定文字行就已讀完, readline()阻塞直到整行讀完,這就是原因。你也知道此行包含名稱;同樣,第二個readline()呼叫返回的時候,你知道這行包含年齡等。 正如你可以看到,該處理程式僅在有新資料讀入時執行,並知道每步的資料是什麼。一旦正在執行的執行緒已處理過讀入的某些資料,該執行緒不會再回退資料(大多如此)。下圖也說明了這條原則:Java IO: 從一個阻塞的流中讀資料) 而一個NIO的實現會有所不同,下面是一個簡單的例子:

ByteBuffer buffer = ByteBuffer.allocate(48);

int bytesRead = inChannel.read(buffer);

注意第二行,從通道讀取位元組到ByteBuffer。當這個方法呼叫返回時,你不知道你所需的所有資料是否在緩衝區內。你所知道的是,該緩衝區包含一些位元組,這使得處理有點困難。
假設第一次 read(buffer)呼叫後,讀入緩衝區的資料只有半行,例如,“Name:An”,你能處理資料嗎?顯然不能,需要等待,直到整行資料讀入快取,在此之前,對資料的任何處理毫無意義。

所以,你怎麼知道是否該緩衝區包含足夠的資料可以處理呢?好了,你不知道。發現的方法只能檢視緩衝區中的資料。其結果是,在你知道所有資料都在緩衝區裡之前,你必須檢查幾次緩衝區的資料。這不僅效率低下,而且可以使程式設計方案雜亂不堪。例如:

ByteBuffer buffer = ByteBuffer.allocate(48);

int bytesRead = inChannel.read(buffer);

while(! bufferFull(bytesRead) ) {

bytesRead = inChannel.read(buffer);

}

bufferFull()方法必須跟蹤有多少資料讀入緩衝區,並返回真或假,這取決於緩衝區是否已滿。換句話說,如果緩衝區準備好被處理,那麼表示緩衝區滿了。

bufferFull()方法掃描緩衝區,但必須保持在bufferFull()方法被呼叫之前狀態相同。如果沒有,下一個讀入緩衝區的資料可能無法讀到正確的位置。這是不可能的,但卻是需要注意的又一問題。

如果緩衝區已滿,它可以被處理。如果它不滿,並且在你的實際案例中有意義,你或許能處理其中的部分資料。但是許多情況下並非如此。下圖展示了“緩衝區資料迴圈就緒”:

Java NIO:從一個通道里讀資料,直到所有的資料都讀到緩衝區裡.

3) 用來處理資料的執行緒數

NIO可讓您只使用一個(或幾個)單執行緒管理多個通道(網路連線或檔案),但付出的代價是解析資料可能會比從一個阻塞流中讀取資料更復雜。

如果需要管理同時開啟的成千上萬個連線,這些連線每次只是傳送少量的資料,例如聊天伺服器,實現NIO的伺服器可能是一個優勢。同樣,如果你需要維持許多開啟的連線到其他計算機上,如P2P網路中,使用一個單獨的執行緒來管理你所有出站連線,可能是一個優勢。一個執行緒多個連線的設計方案如下圖所示:

Java NIO: 單執行緒管理多個連線

如果你有少量的連線使用非常高的頻寬,一次傳送大量的資料,也許典型的IO伺服器實現可能非常契合。下圖說明了一個典型的IO伺服器設計:

Java IO: 一個典型的IO伺服器設計- 一個連線通過一個執行緒處理.

相關推薦

Java NIOIO的區別和比較

選擇器 獲取 如果 得到 提供服務 單獨 每次 取數 details 現代的酒店服務方式跟傳統的區別有兩個:1、增加了一個角色,要有一個專門負責收集客人需求的人。NIO裏對應的就是Selector。2、由阻塞服務方式改為非阻塞服務了,客人吃著的時候服務員不用一直侯在客人旁邊

Java NIO系列教程(十二) Java NIO IO

Java NIO系列教程(十二) Java NIO 與 IO 當學習了 Java NIO 和 IO 的 API 後,一個問題馬上湧入腦海: 我應該何時使用 IO,何時使用 NIO 呢?在本文中,我會盡量清晰地解析 Java NIO 和 IO 的差異、它們的使用場景,以及它們如何影響您的程式碼設計。 下表

Java NIO系列教程(十二) Java NIOIO

作者:Jakob Jenkov   譯者:郭蕾    校對:方騰飛 當學習了Java NIO和IO的API後,一個問題馬上湧入腦海: 我應該何時使用IO,何時使用NIO呢?在本文中,我會盡量清晰地解析Java NIO和IO的差異、它們的使用場景,以及它們如何影響您的程式碼設計。 Java

Java NIO IO之間的區別

概述 Java NIO提供了與標準IO不同的IO工作方式: Channels and Buffers(通道和緩衝區):標準的IO基於位元組流和字元流進行操作的,而NIO是基於通道(Channel)和緩

Java NIO IO

作者:Jakob Jenkov   譯者:郭蕾    校對:方騰飛 當學習了Java NIO和IO的API後,一個問題馬上湧入腦海: 我應該何時使用IO,何時使用NIO呢?在本文中,我會盡量清晰地解析Java NIO和IO的差異、它們的使用場景,以及它們如何影

Java NIO系列教程(12)Java NIOIO

當學習了Java NIO和IO的API後,一個問題馬上湧入腦海: 我應該何時使用IO,何時使用NIO呢?在本文中,我會盡量清晰地解析Java NIO和IO的差異、它們的使用場景,以及它們如何影響您的程式碼設計。 Java NIO和IO的主要區別 下表總結了Java NIO和

Java NIOIO的區別和比較,NIOIO執行緒池效能比較

     傳統的socket IO中,需要為每個連線建立一個執行緒,當併發的連線數量非常巨大時,執行緒所佔用的棧記憶體和CPU執行緒切換的開銷將非常巨大。使用NIO,不再需要為每個執行緒建立單獨的執行緒,可以用一個含有限數量執行緒的執行緒池,甚至一個執行緒來為任意數量的連線服務。由於執行緒數量小於連線數量,所

Java NIOIO的區別

Java.nio 俗稱 New IO (從1.4開始),全稱是Java Non-blocking IO,即非阻塞的IO,為所有的原始型別(boolean型別除外)提供快取支持的資料容器,使用它可以提供非阻塞式的高伸縮性網路IO。 NIO與IO的區別: 1.標準的IO的操作都

Java NIOIONIO的區別

文件 目的 讀取數據 簡單的 什麽 毫無 log 再處理 很多 一、概念 NIO即New IO,這個庫是在JDK1.4中才引入的。NIO和IO有相同的作用和目的,但實現方式不同,NIO主要用到的是塊,所以NIO的效率要比IO高很多。在Java API中提供了

java NIO NIOIO的區別

一、概念      NIO即New IO,但是我認為理解為no-blocking IO(非阻塞IO)更貼切,這個庫是在JDK1.4中才引入的。NIO和IO有相同的作用和目的,但實現方式不同,NIO主要用到的是塊,所以NIO的效率要比IO高很多。在Java

Java NIO 檔案IO-記憶體對映檔案MappedByteBufferzerocopy

在傳統的檔案IO操作中,我們都是呼叫作業系統提供的底層標準IO系統呼叫函式read()、write() ,此時呼叫此函式的程序(在JAVA中即java程序)由當前的使用者態切換到核心態,然後OS的核心程式碼負責將相應的檔案資料讀取到核心的IO緩衝區,然後再把資料

Java nioio

處理程序 lines shell 都在 cto 付出 機制 如何 線程阻塞 當學習了Java NIO和IO的API後,一個問題馬上湧入腦海: 我應該何時使用IO,何時使用NIO呢?在本文中,我會盡量清晰地解析Java NIO和IO的差異、它們的使用場景,以及它們如何影響您

Java NIOIO的主要差別

from 處理程序 java nio dsm 設計 時有 能夠 sock tracking 我應該何時使用IO,何時使用NIO呢?在本文中,我會盡量清晰地解析Jav

Java NIO vs. IO

tutorials http adl pop determine SM oos check cert When studying both the Java NIO and IO API‘s, a question quickly pops into mind: When

NIOIO

uos .com article open .net www. details tails tail https://blog.csdn.net/guoshaogang/article/details/7231318https://blog.csdn.net/qq_1662

JAVA NIOIO

之前有被問到NIO與IO的區別,但是遺憾的是我沒有好好看過NIO。 NIO是什麼 NIO是java1.4之後新出的一套IO介面。NIO相比IO,最大的特點就是非阻塞。 區別: 區別 IO NIO

支撐 Java NIO NodeJS 的底層技術

  眾所周知在近幾個版本的Java中增加了一些對Java NIO、NIO2的支援,與此同時NodeJS技術棧中最為人稱道的優勢之一就是其高效能IO,那麼我們今天要討論的話題就是支撐這些技術的底層技術。   開始之前先要提出的一個問題是:   為什麼NodeJS和Java

【 專欄 】- Java NIO Netty 網路程式設計學習筆記

Java NIO 與 Netty 網路程式設計學習筆記 以一個IM聊天功能的實現。記錄筆者從最原始的阻塞IO(BIO)到JDK1.4提供的非阻塞IO,再到JDK 1.7 非同步IO的學習筆記,最後到Netty框架的學習筆記。

NIOIO的區別

JAVA NIO vs IO 當我們學習了Java NIO和IO後,我們很快就會思考一個問題: 什麼時候應該使用IO,什麼時候我應該使用NIO 在下文中我會嘗試用例子闡述java NIO 和IO的區別,以及它們對你的設計會有什麼影響 Java NIO和IO的主要區別 IO

二十三、NIOIO

java NIO由以下幾個核心部分組成: Channels(通道) Buffers(緩衝區) Selectors(選擇器) 其他 Channel和Buffer: 所有的IO再NIO中都從一個Channel開始.Channel有點像流,資料可以從Ch