Netty學習筆記 3.2 NIO和BIO比較及原理示意圖
標簽: netty學習筆記 java nio netty 數據庫
Netty學習筆記 3.2 NIO和BIO比較及原理示意圖
NIO 和 BIO 的比較
BIO 以流的方式處理數據,而 NIO 以塊的方式處理數據,塊 I/O 的效率比流 I/O 高很多
BIO 是阻塞的,NIO 則是非阻塞的
BIO基于字節流和字符流進行操作,而 NIO 基于 **Channel(通道)和 Buffer(緩沖區)**進行操作,數據總是從通道讀取到緩沖區中,或者從緩沖區寫入到通道中。Selector(選擇器)用于監聽多個通道的事件(比如:連接請求,數據到達等),因此使用單個線程就可以監聽多個客戶端通道
NIO 三大核心原理示意圖
一張圖描述NIO 的 Selector 、 Channel 和 Buffer 的關系
**
Selector 、 Channel 和 Buffer 的關系圖(簡單版)
**
關系圖的說明:
每個channel 都會對應一個Buffer
Selector 對應一個線程, 一個線程對應多個channel(連接)
該圖反應了有三個channel 注冊到 該selector //程序
程序切換到哪個channel 是有事件決定的, Event 就是一個重要的概念
Selector 會根據不同的事件,在各個通道上切換
Buffer 就是一個內存塊 , 底層是有一個數組
數據的讀取寫入是通過Buffer, 這個和BIO , BIO 中要么是輸入流,或者是輸出流, 不能雙向,但是NIO的Buffer 是可以讀也可以寫, 需要 flip 方法切換
channel 是雙向的, 可以返回底層操作系統的情況, 比如Linux , 底層的操作系統通道就是雙向的.
緩沖區(Buffer)
基本介紹
緩沖區(Buffer):緩沖區本質上是一個可以讀寫數據的內存塊,可以理解成是一個容器對象(含數組),該對象提供了一組方法,可以更輕松地使用內存塊,,緩沖區對象內置了一些機制,能夠跟蹤和記錄緩沖區的狀態變化情況。Channel 提供從文件、網絡讀取數據的渠道,但是讀取或寫入的數據都必須經由 Buffer,如圖: 【后面舉例說明】
Buffer 類及其子類
- 在 NIO 中,Buffer 是一個頂層父類,它是一個抽象類, 類的層級關系圖:
常用Buffer子類一覽
ByteBuffer,存儲字節數據到緩沖區
ShortBuffer,存儲字符串數據到緩沖區
CharBuffer,存儲字符數據到緩沖區
IntBuffer,存儲整數數據到緩沖區
LongBuffer,存儲長整型數據到緩沖區
DoubleBuffer,存儲小數到緩沖區
FloatBuffer,存儲小數到緩沖區
Buffer 類及其子類
Buffer類定義了所有的緩沖區都具有的四個屬性來提供關于其所包含的數據元素的信息:
// Invariants: mark <= position <= limit <= capacity
private int mark = -1;
private int position = 0;
private int limit;
private int capacity;
Buffer 類及其子類
Buffer類相關方法一覽
public abstract class Buffer {
//JDK1.4時,引入的api
public final int capacity( )//返回此緩沖區的容量
public final int position( )//返回此緩沖區的位置
public final Buffer position (int newPositio)//設置此緩沖區的位置
public final int limit( )//返回此緩沖區的限制
public final Buffer limit (int newLimit)//設置此緩沖區的限制
public final Buffer mark( )//在此緩沖區的位置設置標記
public final Buffer reset( )//將此緩沖區的位置重置為以前標記的位置
public final Buffer clear( )//清除此緩沖區, 即將各個標記恢復到初始狀態,但是數據并沒有真正擦除, 后面操作會覆蓋
public final Buffer flip( )//反轉此緩沖區
public final Buffer rewind( )//重繞此緩沖區
public final int remaining( )//返回當前位置與限制之間的元素數
public final boolean hasRemaining( )//告知在當前位置和限制之間是否有元素
public abstract boolean isReadOnly( );//告知此緩沖區是否為只讀緩沖區
//JDK1.6時引入的api
public abstract boolean hasArray();//告知此緩沖區是否具有可訪問的底層實現數組
public abstract Object array();//返回此緩沖區的底層實現數組
public abstract int arrayOffset();//返回此緩沖區的底層實現數組中第一個緩沖區元素的偏移量
public abstract boolean isDirect();//告知此緩沖區是否為直接緩沖區
}
ByteBuffer
從前面可以看出對于 Java 中的基本數據類型(boolean除外),都有一個 Buffer 類型與之相對應,最常用的自然是ByteBuffer 類(二進制數據),該類的主要方法如下:
public abstract class ByteBuffer {
//緩沖區創建相關api
public static ByteBuffer allocateDirect(int capacity)//創建直接緩沖區
public static ByteBuffer allocate(int capacity)//設置緩沖區的初始容量
public static ByteBuffer wrap(byte[] array)//把一個數組放到緩沖區中使用
//構造初始化位置offset和上界length的緩沖區
public static ByteBuffer wrap(byte[] array,int offset, int length)
//緩存區存取相關API
public abstract byte get( );//從當前位置position上get,get之后,position會自動+1
public abstract byte get (int index);//從絕對位置get
public abstract ByteBuffer put (byte b);//從當前位置上添加,put之后,position會自動+1
public abstract ByteBuffer put (int index, byte b);//從絕對位置上put
}
通道(Channel)
基本介紹
NIO的通道類似于流,但有些區別如下:
通道可以同時進行讀寫,而流只能讀或者只能寫
通道可以實現異步讀寫數據
通道可以從緩沖讀數據,也可以寫數據到緩沖:
基本介紹
BIO 中的 stream 是單向的,例如 FileInputStream 對象只能進行讀取數據的操作,而 NIO 中的通道(Channel)是雙向的,可以讀操作,也可以寫操作。
Channel在NIO中是一個接口public interface Channel extends Closeable{}
常用的 Channel 類有:FileChannel、DatagramChannel、ServerSocketChannel 和 SocketChannel。【ServerSocketChanne 類似 ServerSocket , SocketChannel 類似 Socket】
FileChannel 用于文件的數據讀寫,DatagramChannel 用于 UDP 的數據讀寫,ServerSocketChannel 和 SocketChannel 用于 TCP 的數據讀寫。
FileChannel 類
FileChannel主要用來對本地文件進行 IO 操作,常見的方法有
public int read(ByteBuffer dst) ,從通道讀取數據并放到緩沖區中
public int write(ByteBuffer src) ,把緩沖區的數據寫到通道中
public long transferFrom(ReadableByteChannel src, long position, long count),從目標通道中復制數據到當前通道
public long transferTo(long position, long count, WritableByteChannel target),把數據從當前通道復制給目標通道
智能推薦
netty權威指南學習筆記一——NIO入門(1)BIO
公司的一些項目采用了netty框架,為了加速適應公司開發,本博主認真學習netty框架,前一段時間主要看了看書,發現編程這東西,不上手還是覺得差點什么,于是為了加深理解,深入學習,本博主還是決定多動手,一方面記錄一些總結性的思考性東西,另一方面也為日后復習查看留下一些東西。 那么廢話少說,現在開始,首先在進入netty學習之前,我們是要認識一下IO并引出NIO的概念。 與IO相關的幾種...
鏈表(單向、雙向、單向循環、雙向循環)學習過程總結——有源代碼、注釋和示意圖
前段時間學習了數據結構的部分知識,然后到上個星期別人問相關問題的餓時候發現自己對鏈表的知識都有些模糊了,主要還是有些細節的地方記不太清楚,所以就萌生了寫這篇博客的想法,一是要重新復習一下鏈表的相關知識,二呢用C++重新寫一遍,熟悉C++語言。之前用C語言實現鏈表操作的時候也寫過幾篇博客,但是重點都是體現在代碼部分,示意圖都是從網站上下過來的或...
React學習之旅Part8:通過例子和示意圖弄懂React的生命周期
一、概述 什么是生命周期 每個組件的實例從創建到運行再到銷毀 在這個過程中的特定階段會觸發一系列的事件 這些事件就叫做組件的生命周期函數 React的組件生命周期函數 React組件的生命周期分為三部分:創建 運行 銷毀 組件創建階段 (在組件的整個生命周期中只會被執行一次) componentWillMount / 組件將要掛載 render / 渲染虛擬DOM元素 componentDidMo...
Netty學習筆記(1)——NIO概述
1. 傳統IO(BIO)存在的問題 同步阻塞 也就是傳統IO(也就是InputStream、OutputStream等Java中IO包下的類以及 java.net下面提供的部分網絡 API,比如 Socket、ServerSocket、HttpURLConnection 也歸類到同步阻塞 IO 類庫,因為網絡通信同樣是 IO 行為。)在進行讀寫操...
猜你喜歡
freemarker + ItextRender 根據模板生成PDF文件
1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...
電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!
Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...
requests實現全自動PPT模板
http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...