Java NIO基本介紹
- java non-blocking?I/O?稱為NIO(也叫New?IO)。JDK4開始提供,同步非阻塞
- 相關(guān)內(nèi)容在?java.nio 包及子包下,對java.io 包中的很多類進(jìn)行改寫。
- 三大核心: Channel(通道),Buffer(緩沖區(qū)),Selector(選擇器)
- NIO是面向緩沖區(qū)或者面向塊編程的。數(shù)據(jù)讀取到一個它后處理的緩沖區(qū),需要時可在緩沖區(qū)中前后移動,這就增加了處理過程中的靈活性,使用它可以提供非阻塞式的高伸縮性網(wǎng)絡(luò)
- NIO的非阻塞模式,使一個線程從某通道發(fā)送請求或者讀取數(shù)據(jù),但是它僅能得到目前可用的數(shù)據(jù),如果目前沒有數(shù)據(jù)可用時,就什么都不會獲取,而不是保持線程阻塞,所以直至數(shù)據(jù)可以讀取之前,該線程可以繼續(xù)做其他的事情。
- 通俗理解: NIO 是可以做到用一個線程來處理多個操作。假設(shè)有 10000 個請求過來,根據(jù)實際情況,可以分配50 或者 100 個線程來處理。不像之前的阻塞IO 那樣,非得分配 10000 個。
- HTTP2.0 使用了多路復(fù)用的技術(shù),做到同一個連接并發(fā)處理多個請求,而且并發(fā)請求的數(shù)量比 HTTP1.1 大了好幾個數(shù)量級
- 基本案例:
NIO 和 BIO 的比較
- BIO以流的方式處理數(shù)據(jù),而NIO以塊的方式處理數(shù)據(jù),I/O塊的效率比I/O流高很多
- BIO 是阻塞的,NIO則是非阻塞的
- BIO 基于字節(jié)流和字符流進(jìn)行操作,而NIO基于Channel(通道)和Buffer(緩沖區(qū))進(jìn)行操作,數(shù)據(jù)總是從通道讀取到緩沖區(qū)中,或者從緩沖區(qū)寫入到通道中。Selector 選擇器用于監(jiān)聽多個通道的事件(比如:連接請求,數(shù)據(jù)到達(dá)等),因此使用單個線程就可以監(jiān)聽多個客戶端通道
Selector、Channel 和 Buffer 的關(guān)系圖
- 每個channel都會對應(yīng)一個Buffer
- 一個Selector對應(yīng)一個線程
- 多個channel會注冊到其selector
- Selector會根據(jù)不同的Event,在各個Channel上切換
- channel 是雙向的,可以返回底層操作系統(tǒng)的情況,比如Linux,底層的操作系統(tǒng)通道就是雙向的.
- Buffer是一個內(nèi)存塊,底層是一個數(shù)組
- 數(shù)據(jù)的讀取寫入是通過 Buffer,這個和BIO有所區(qū)別,BIO 中要么是輸入流,或者是輸出流,不能雙向,但是NIO的Buffer是可以讀也可以寫,需要flip()切換
?
緩沖區(qū)(Buffer)
- Buffer本質(zhì)上是一個可以讀寫數(shù)據(jù)的內(nèi)存塊,可以理解成是一個容器對象(含數(shù)組),該對象提供了一組方法,可以更輕松地使用內(nèi)存塊,Buffer對象內(nèi)置了一些機(jī)制,能夠跟蹤和記錄緩沖區(qū)的狀態(tài)變化情況。Channel 讀寫的數(shù)據(jù)都必須經(jīng)由Buffer
- Buffer是父類、抽象類,類的層級關(guān)系圖
-
常用Buffer子類
- ByteBuffer?存儲字節(jié)數(shù)據(jù)到緩沖區(qū)
- shortBuffer?存儲字符串?dāng)?shù)據(jù)到緩沖區(qū)
- CharBuffer?存儲字符數(shù)據(jù)到緩沖區(qū)
- IntBuffer?存儲整數(shù)數(shù)據(jù)到緩沖區(qū)
- LongBuffer?存儲長整型教據(jù)到緩沖區(qū)
- DoubleBuffer?存儲小數(shù)到緩沖區(qū)
- FloatBuffer?存儲小數(shù)到緩沖區(qū)
-
這些Buffer都把數(shù)據(jù)存于自己類型的數(shù)組
- Buffer類的四個屬性:
- Capacity:容量,即可以容納的最大數(shù)據(jù)量;在緩沖區(qū)創(chuàng)建時被設(shè)定并且不能改變
- Limit:表示緩沖區(qū)的當(dāng)前終點,不能對緩沖區(qū)超過極限的位置進(jìn)行讀寫操作。且極限是可以修改的
- Position:位置,下一個要被讀寫的元素的索引,每次讀寫緩沖區(qū)數(shù)據(jù)時都會改變改值,為下次讀寫做準(zhǔn)備
- Mark:標(biāo)記
Buffer類相關(guān)方法
public abstract class Buffer{
//JDK1.4時,引入的api
public final int capacity()//返回此緩沖區(qū)的容量
public final int position()//返回此緩沖區(qū)的位置
public final Buffer position(int newPositio)//設(shè)置此緩沖區(qū)的位置
public final int limit()//返回此緩沖區(qū)的限制
public final Buffer limit(int newLimit)//設(shè)置此緩沖區(qū)的限制
public final Buffer mark()//在此緩沖區(qū)的位置設(shè)置標(biāo)記
public final Buffer reset()//將此緩沖區(qū)的位置重置為以前標(biāo)記的位置
public final Buffer clear()//清除此緩沖區(qū),即將各個標(biāo)記恢復(fù)到初始狀態(tài),但是數(shù)據(jù)并沒有真正擦除,
public final Buffer flip()//反轉(zhuǎn)此緩沖區(qū)
public final Buffer rewind()//重繞此緩沖區(qū)
public final int remaining()//返回當(dāng)前位置與限制之間的元素數(shù)
public final boolean hasRemaining()//告知在當(dāng)前位置和限制之間是否有元素
public abstract boolean isReadOnly()://告知此緩沖區(qū)是否為只讀緩沖區(qū)
//JDK1.6時引入的api
public abstract boolean hasArray();//告知此緩沖區(qū)是否具有可訪問的底層實現(xiàn)數(shù)組
public abstract Object array();//返回此緩沖區(qū)的底層實現(xiàn)數(shù)組
public abstract int arrayOffset();/返回此緩沖區(qū)的底層實現(xiàn)數(shù)組中第一個緩沖區(qū)元素的偏移量
public abstract boolean is Direct();//告知此緩沖區(qū)是否為直接緩沖區(qū)
}
ByteBuffer
- 除了boolean,其他基本類型都有一個Buffer類型與之相對應(yīng),最常用的自然是 ByteBuffer 類(二進(jìn)制數(shù)據(jù)),該類的主要方法如下:
public abstract class ByteBuffer(
//緩沖區(qū)創(chuàng)建相關(guān)api
public static ByteBuffer allocateDirect(int capacity)//創(chuàng)建直接緩沖區(qū)
public static ByteBuffer allocate(int capacity)//設(shè)置緩沖區(qū)的初始容量
public static ByteBuffer wrap(byte[] array)//把一個數(shù)組放到緩沖區(qū)中使用
//構(gòu)造初始化位置offset和上界length的緩沖區(qū)
public static ByteBuffer wrap(byte[] array,int offset, int length)
//緩存區(qū)存取相關(guān)API
public abstract byte get()//從當(dāng)前位置position上get,get之后,position會自動+1
public abstract byte get(int index);//從絕對位置get
public abstract ByteBuffer put(byte b);//從當(dāng)前位置上添加,put之后,position會自動+1
public abstract ByteBuffer put(int index,byte b);//從絕對位置上put
關(guān)于Buffer的注意事項和細(xì)節(jié)
- ByteBuffer支持類型化的put和get,數(shù)據(jù)類型必須保持一致,否則可能有 BufferUnderflowException 異常。
- Buffer支持轉(zhuǎn)換為只讀buffer,調(diào)用asReadOnlyBuffer()
- NIO還提供了MappedByteBuffer,可以讓文件直接在內(nèi)存(堆外內(nèi)存) 中進(jìn)行修改,而如何同步到文件由NIO來完成.
- NIO還支持通過多個Buffer(buffer數(shù)組)完成讀寫操作即 Scattering(分散)和 Gathering(合并)
?文章來源:http://www.zghlxwxcb.cn/news/detail-794456.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-794456.html
到了這里,關(guān)于Netty開篇——NIO章上(三)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!