劍指Offer(類庫)——Java的IO機制

本文主要介紹一下BIO、NIO、AIO

Block-IO:基於字節流的InputStream和OutputStream,基於字符流的Reader和Writer,同時也包括Socket那些java.net包下的類等。

BIO的屬性是同步阻塞的,優點就是寫起來簡單缺點是效率太低。
在這裏插入圖片描述
NonBlock-IO:在JDK4中引入了NIO,它是一種構建多路複用的,同步非阻塞的IO操作提供了Selector、Channel、Buffer等新的抽象,同時提供了更底層的數據操作方式。
在這裏插入圖片描述
下面介紹一個NIO的三大核心:Channels,Buffers,Selectors。
NIO-Channel
在這裏插入圖片描述
Channel有點像流,一個的數據都是從Channel開始然後讀到Buffer中再從Buffer寫到Channel中。

NIO的Channels有以下幾種類型,從方法名可以看出有UDP的Channel有文件Channel還有TCP的Channel:

  • FileChannel
  • DatagramChannel
  • SocketChannel
  • ServerSocketChannel

其中,FileChannel中有兩個有意思的方法:

  • transferTo:把FileChannel中的數據拷貝到另外一個Channel
  • transferFrom:把另外一個Channel中的數據拷貝到FileChannel

該Channel避免了兩次用戶態和內核態之間的上下文切換,即“零拷貝”,效率較高。

NIO-Buffer

有以下幾種類型,進行緩衝流的數據屬性修飾:

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

NIO-Selector

如果連接打開了多個通道,但是每個通道的流量都很低就可以使用Selector。
在這裏插入圖片描述
另外NIO的底層也採用了IO的多路複用:調用系統級別的select/poll/epoll,意思就是說可以單線程處理多路IO。

然後簡單介紹一下三者以及三者的區別:

支持一個線程所能打開的最大連接數

select:單個進程能打開的最大連接數由FD_SETSIZE宏定義,其大小是32個整數的大小,我們可以對其進行修改,然後重新編譯內核,但是性能無法保證,需要進一步測試

poll:本質上和select沒有區別,但是沒有最大連接數的限制,原因是因爲他是基於鏈表去存儲的

epoll:雖然連接數由上線,但是很大,1G內存的機器可以打開10萬左右的連接

面對文件句柄DF劇增之後也會帶來IO效率問題

select:因爲每次調用的時候都會對連接進行線性遍歷,所以隨着FD的增加會造成遍歷速度的線性下降的性能問題

poll:同上

epoll:由於epoll是根據每個fd上的callback函數來實現的,只有活躍的socket纔會主動調用callback,所以在活躍socket較少的情況下,使用epoll不會有線性下降的性能問題,但是所有socket都很活躍的情況下可能會有性能上的問題

在消息的傳遞方式上

select:內核需要將消息傳遞到用戶空間,需要內核的拷貝工作

poll:同上

通過內核和用戶空間共享一塊內存來實現性能很高

JDK7又引入了AIO:基於事件和回調機制
在這裏插入圖片描述
AIO屬於異步模型,也就是說處理IO的時候可以同時處理別的事情,那我們應該如何進一步加工處理結果呢?

  1. 基於回調:實現CompletionHandler接口,調用的時候觸發回調函數;
  2. 返回Future:通過isDone()查看是否準備好,通過get()等待返回數據
    在這裏插入圖片描述
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章