java NIO原理

NIO中的重要概念 通道、緩衝區、選擇器java

  • 通道:相似於流,
    • 可是能夠異步讀寫數據(流只能同步讀寫),
    • 通道是雙向的,(流是單向的),
  • 通道的數據老是要先讀到一個buffer 或者 從一個buffer寫入,
    • 即通道與buffer進行數據交互。

通道類型:  服務器

  • FileChannel:從文件中讀寫數據。  
    • FileChannel比較特殊,
    • 它能夠與通道進行數據交互,
    • 不能切換到非阻塞模式,
  • DatagramChannel:能經過UDP讀寫網絡中的數據。  
  • SocketChannel:能經過TCP讀寫網絡中的數據。  
    • 套接字通道(SocketChannel)能夠切換到非阻塞模式;
  • ServerSocketChannel:能夠監聽新進來的TCP鏈接,像Web服務器那樣。
    • 對每個新進來的鏈接都會建立一個SocketChannel。

緩衝區 - 本質上是一塊能夠存儲數據的內存,被封裝成了buffer對象而已!網絡

緩衝區類型:app

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

 經常使用方法:異步

    • allocate() - 分配一塊緩衝區  
    • put() -  向緩衝區寫數據
    • get() - 向緩衝區讀數據  
    • flip() - 將緩衝區從寫模式切換到讀模式,limit 指向有效數據末尾
    • rewind() - 將緩衝區從寫模式切換到讀模式,limit 指向capacity 
    • clear() - 從讀模式切換到寫模式,不會清空數據,
      • 但後續寫數據會覆蓋原來的數據,
      • 即便有部分數據沒有讀,也會被遺忘;  
    • compact() - 從讀數據切換到寫模式,數據不會被清空,
      • 會將全部未讀的數據copy到緩衝區頭部,
      • 後續寫數據不會覆蓋,而是在這些數據以後寫數據
    • mark() - 對position作出標記,配合reset使用
    • reset() - 將position置爲標記值  

緩衝區的一些屬性:socket

  • capacity - 緩衝區大小(容量),
    • 不管是讀模式仍是寫模式,此屬性值不會變;
  • position - 寫數據時,position表示當前寫的位置,
    • 每寫一個數據,會向下移動一個數據單元,
    • 初始爲0;最大爲capacity - 1
    • 切換到讀模式時,position會被置爲0,表示當前讀的位置
  • limit - 寫模式下,limit 至關於capacity 表示最多能夠寫多少數據,
    • 切換到讀模式時,limit 等於原先的position,表示最多能夠讀多少數據。

選擇器:至關於一個觀察者,spa

  • 用來監聽通道感興趣的事件,
  • 一個選擇器能夠綁定多個通道;

通道向選擇器註冊時,須要指定感興趣的事件,選擇器支持如下事件:rest

  • SelectionKey.OP_READ表示關注讀數據就緒事件 
  • SelectionKey.OP_WRITE表示關注寫數據就緒事件 
  • SelectionKey.OP_CONNECT表示關注socket channel的鏈接完成事件 
  • SelectionKey.OP_ACCEPT表示關注server-socket channel的accept事件 

若是你對不止一種事件感興趣,code

  • 那麼能夠用「位或」操做符將常量鏈接起來,以下:
    • int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE; 

通道向選擇器註冊時,會返回一個 SelectionKey對象,具備以下屬性server

  • interest集合
  • ready集合  
  • Channel  
  • Selector
  • 附加的對象(可選) 

用「位與」操做interest 集合和給定的SelectionKey常量,

  • 能夠肯定某個肯定的事件是否在interest 集合中。
    • int interestSet = selectionKey.interestOps();  
       
      boolean isInterestedInAccept  = interestSet & SelectionKey.OP_ACCEPT;
      boolean isInterestedInConnect = interestSet & SelectionKey.OP_CONNECT;  
      boolean isInterestedInRead    = interestSet & SelectionKey.OP_READ;  
      boolean isInterestedInWrite   = interestSet & SelectionKey.OP_WRITE;

       

  • ready 集合是通道已經準備就緒的操做的集合。
    • 在一次選擇(Selection)以後,你會首先訪問這個ready set。
    • 能夠這樣訪問ready集合: 
      • int readySet = selectionKey.readyOps();
  • 四個方法獲取已就緒事件,返回值爲boolean:
    • selectionKey.isAcceptable();  
      selectionKey.isConnectable();  
      selectionKey.isReadable();  
      selectionKey.isWritable();
  • 能夠將一個對象或者更多信息附着到SelectionKey上,
    • 即記錄在附加對象上,方法以下:
      • selectionKey.attach(theObject);  
        Object attachedObj = selectionKey.attachment();

能夠經過選擇器的select方法獲取是否有就緒的通道;

  • int select()  
  • int select(long timeout)  
  • int selectNow()
相關文章
相關標籤/搜索