Java NIO:NIO概述

Java NIO:NIO概述html

  在上一篇博文中講述了幾種IO模型,如今咱們開始進入Java NIO編程主題。NIO是Java 4裏面提供的新的API,目的是用來解決傳統IO的問題。本文下面分別從Java NIO的幾個基礎概念介紹起。java

  如下是本文的目錄大綱:編程

  一.NIO中的幾個基礎概念數組

  二.Channel網絡

  三.Buffer多線程

  四.Selector函數

  如有不正之處,請多多諒解並歡迎批評指正。spa

  請尊重做者勞動成果,轉載請標明原文連接:.net

   http://www.cnblogs.com/dolphin0520/p/3919162.html線程

一.NIO中的幾個基礎概念

  在NIO中有幾個比較關鍵的概念:Channel(通道),Buffer(緩衝區),Selector(選擇器)。

  首先從Channel提及吧,通道,顧名思義,就是通向什麼的道路,爲某個提供了渠道。在傳統IO中,咱們要讀取一個文件中的內容,一般是像下面這樣讀取的:

public class Test {
    public static void main(String[] args) throws IOException  {
    	File file = new File("data.txt");
    	InputStream inputStream = new FileInputStream(file);
    	byte[] bytes = new byte[1024];
    	inputStream.read(bytes);
    	inputStream.close();
    }   
}

   這裏的InputStream實際上就是爲讀取文件提供一個通道的。

  所以能夠將NIO 中的Channel同傳統IO中的Stream來類比,可是要注意,傳統IO中,Stream是單向的,好比InputStream只能進行讀取操做,OutputStream只能進行寫操做。而Channel是雙向的,既可用來進行讀操做,又可用來進行寫操做。

  Buffer(緩衝區),是NIO中很是重要的一個東西,在NIO中全部數據的讀和寫都離不開Buffer。好比上面的一段代碼中,讀取的數據時放在byte數組當中,而在NIO中,讀取的數據只能放在Buffer中。一樣地,寫入數據也是先寫入到Buffer中。

  下面介紹一下NIO中最核心的一個東西:Selector。能夠說它是NIO中最關鍵的一個部分,Selector的做用就是用來輪詢每一個註冊的Channel,一旦發現Channel有註冊的事件發生,便獲取事件而後進行處理。

  好比看下面的這個例子:

   

  用單線程處理一個Selector,而後經過Selector.select()方法來獲取到達事件,在獲取了到達事件以後,就能夠逐個地對這些事件進行響應處理。

二.Channel

  在前面已經提到,Channel和傳統IO中的Stream很類似。雖然很類似,可是有很大的區別,主要區別爲:通道是雙向的,經過一個Channel既能夠進行讀,也能夠進行寫;而Stream只能進行單向操做,經過一個Stream只能進行讀或者寫;

  如下是經常使用的幾種通道:

  • FileChannel
  • SocketChanel
  • ServerSocketChannel
  • DatagramChannel

  經過使用FileChannel能夠從文件讀或者向文件寫入數據;經過SocketChannel,以TCP來向網絡鏈接的兩端讀寫數據;經過ServerSocketChanel可以監聽客戶端發起的TCP鏈接,併爲每一個TCP鏈接建立一個新的SocketChannel來進行數據讀寫;經過DatagramChannel,以UDP協議來向網絡鏈接的兩端讀寫數據。

  下面給出經過FileChannel來向文件中寫入數據的一個例子:

public class Test {
    public static void main(String[] args) throws IOException  {
    	File file = new File("data.txt");
    	FileOutputStream outputStream = new FileOutputStream(file);
    	FileChannel channel = outputStream.getChannel();
    	ByteBuffer buffer = ByteBuffer.allocate(1024);
    	String string = "java nio";
    	buffer.put(string.getBytes());
    	buffer.flip();     //此處必需要調用buffer的flip方法
    	channel.write(buffer);
    	channel.close();
    	outputStream.close();
    }   
}

   經過上面的程序會向工程目錄下的data.txt文件寫入字符串"java nio",注意在調用channel的write方法以前必須調用buffer的flip方法,不然沒法正確寫入內容,至於具體緣由將在下篇博文中具體講述Buffer的用法時闡述。

三.Buffer

  Buffer,故名思意,緩衝區,其實是一個容器,是一個連續數組。Channel提供從文件、網絡讀取數據的渠道,可是讀取或寫入的數據都必須經由Buffer。具體看下面這張圖就理解了:

  上面的圖描述了從一個客戶端向服務端發送數據,而後服務端接收數據的過程。客戶端發送數據時,必須先將數據存入Buffer中,而後將Buffer中的內容寫入通道。服務端這邊接收數據必須經過Channel將數據讀入到Buffer中,而後再從Buffer中取出數據來處理。

  在NIO中,Buffer是一個頂層父類,它是一個抽象類,經常使用的Buffer的子類有:

  • ByteBuffer
  • IntBuffer
  • CharBuffer
  • LongBuffer
  • DoubleBuffer
  • FloatBuffer
  • ShortBuffer

  若是是對於文件讀寫,上面幾種Buffer均可能會用到。可是對於網絡讀寫來講,用的最多的是ByteBuffer。

  關於Buffer的具體使用以及它的limit、posiion和capacity這幾個屬性的理解在下一篇文章中講述。

四.Selector

  Selector類是NIO的核心類,Selector可以檢測多個註冊的通道上是否有事件發生,若是有事件發生,便獲取事件而後針對每一個事件進行相應的響應處理。這樣一來,只是用一個單線程就能夠管理多個通道,也就是管理多個鏈接。這樣使得只有在鏈接真正有讀寫事件發生時,纔會調用函數來進行讀寫,就大大地減小了系統開銷,而且沒必要爲每一個鏈接都建立一個線程,不用去維護多個線程,而且避免了多線程之間的上下文切換致使的開銷。

  與Selector有關的一個關鍵類是SelectionKey,一個SelectionKey表示一個到達的事件,這2個類構成了服務端處理業務的關鍵邏輯。

  關於Selector類的具體使用將在後續文章中闡述。

  參考資料:

  http://blog.csdn.net/wuxianglong/article/details/6604817

  http://www.360doc.com/content/12/0515/11/1542811_211144310.shtml

  http://www.iteye.com/topic/834447

  http://weixiaolu.iteye.com/blog/1479656

  http://ifeve.com/overview/

相關文章
相關標籤/搜索