nio buffer 用法
NIO的Buffer(緩沖區(qū))本質(zhì)上是一個內(nèi)存塊吏奸,既可以寫入數(shù)據(jù)憨栽,也可以從中讀取數(shù)據(jù)。NIO的Buffer類豺型,是一個抽象類,位于java.nio包中买乃,其內(nèi)部是一個內(nèi)存塊(數(shù)組)姻氨。NIO的Buffer與普通的內(nèi)存塊(Java數(shù)組)不同的是:NIOBuffer對象,提供了一組更加有效的方法剪验,用來進行寫入和讀取的交替訪問肴焊。需要強調(diào)的是:Buffer類是一個非線程安全類.
1. Buffer類Buffer類是一個抽象類前联,對應(yīng)于Java的主要數(shù)據(jù)類型,在NIO中有8種緩沖區(qū)類娶眷,分別如下:ByteBuffer似嗤、CharBuffer、DoubleBuffer届宠、FloatBuffer烁落、IntBuffer、LongBuffer豌注、ShortBuffer伤塌、MappedByteBuffer。前7種Buffer類型轧铁,覆蓋了能在IO中傳輸?shù)乃械腏ava基本數(shù)據(jù)類型每聪。第8種類型MappedByteBuffer是專門用于內(nèi)存映射的一種ByteBuffer類型。實際上齿风,使用最多的還是ByteBuffer二進制字節(jié)緩沖區(qū)類型药薯,后面會看到。
2.capacity屬性Buffer類的capacity屬性聂宾,表示內(nèi)部容量的大小果善。
? ? ? ?一旦寫入的對象數(shù)量超過了capacity容量诊笤,緩沖區(qū)就滿了系谐,不能再寫入了。Buffer類的capacity屬性一旦初始化讨跟,就不能再改變纪他。原因是什么呢?Buffer類的對象在初始化時晾匠,會按照capacity分配內(nèi)部的內(nèi)存茶袒。在內(nèi)存分配好之后,它的大小當(dāng)然就不能改變了凉馆。再強調(diào)一下薪寓,capacity容量不是指內(nèi)存塊byte[]數(shù)組的字節(jié)的數(shù)量。capacity容量指的是寫入的數(shù)據(jù)對象的數(shù)量澜共。前面講到向叉,Buffer類是一個抽象類,Java不能直接用來新建對象嗦董。使用的時候母谎,必須使用Buffer的某個子類,例如使用DoubleBuffer京革,則寫入的數(shù)據(jù)是double類型奇唤,如果其capacity是100幸斥,那么我們最多可以寫入100個double數(shù)據(jù)。
3.position屬性Buffer類的position屬性咬扇,表示當(dāng)前的位置甲葬。
????????position屬性與緩沖區(qū)的讀寫模式有關(guān)。在不同的模式下冗栗,position屬性的值是不同的演顾。當(dāng)緩沖區(qū)進行讀寫的模式改變時,position會進行調(diào)整隅居。
????在寫入模式下钠至,position的值變化規(guī)則如下:
(1)在剛進入到寫模式時,position值為0胎源,表示當(dāng)前的寫入位置為從頭開始棉钧。
(2)每當(dāng)一個數(shù)據(jù)寫到緩沖區(qū)之后,position會向后移動到下一個可寫的位置涕蚤。
(3)初始的position值為0宪卿,最大可寫值position為limit–1。當(dāng)position值達到limit時万栅,緩沖區(qū)就已經(jīng)無空間可寫了佑钾。
在讀模式下,position的值變化規(guī)則如下:
(1)當(dāng)緩沖區(qū)剛開始進入到讀模式時烦粒,position會被重置為0休溶。
(2)當(dāng)從緩沖區(qū)讀取時,也是從position位置開始讀扰她。讀取數(shù)據(jù)后兽掰,position向前移動到下一個可讀的位置。(3)position最大的值為最大可讀上限limit徒役,當(dāng)position達到limit時孽尽,表明緩沖區(qū)已經(jīng)無數(shù)據(jù)可讀。起點在哪里呢忧勿?當(dāng)新建一個緩沖區(qū)時杉女,緩沖區(qū)處于寫入模式,這時是可以寫數(shù)據(jù)的鸳吸。數(shù)據(jù)寫入后熏挎,如果要從緩沖區(qū)讀取數(shù)據(jù),這就要進行模式的切換层释,可以使用(即調(diào)用)flip翻轉(zhuǎn)方法婆瓜,將緩沖區(qū)變成讀取模式。在這個flip翻轉(zhuǎn)過程中,position會進行非常巨大的調(diào)整廉白,具體的規(guī)則是:position由原來的寫入位置个初,變成新的可讀位置,也就是0猴蹂,表示可以從頭開始讀院溺。flip翻轉(zhuǎn)的另外一半工作,就是要調(diào)整limit屬性磅轻。
3.limit屬性Buffer類的limit屬性珍逸,表示讀寫的最大上限。
????????limit屬性聋溜,也與緩沖區(qū)的讀寫模式有關(guān)谆膳。在不同的模式下,limit的值的含義是不同的撮躁。在寫模式下漱病,limit屬性值的含義為可以寫入的數(shù)據(jù)最大上限。在剛進入到寫模式時把曼,limit的值會被設(shè)置成緩沖區(qū)的capacity容量值杨帽,表示可以一直將緩沖區(qū)的容量寫滿。在讀模式下嗤军,limit的值含義為最多能從緩沖區(qū)中讀取到多少數(shù)據(jù)注盈。
一般來說,是先寫入再讀取叙赚。當(dāng)緩沖區(qū)寫入完成后老客,就可以開始從Buffer讀取數(shù)據(jù),可以使用flip翻轉(zhuǎn)方法纠俭,這時沿量,limit的值也會進行非常大的調(diào)整浪慌。具體如何調(diào)整呢冤荆?將寫模式下的position值,設(shè)置成讀模式下的limit值权纤,也就是說钓简,將之前寫入的最大數(shù)量,作為可以讀取的上限值汹想。在flip翻轉(zhuǎn)時外邓,屬性的調(diào)整,將涉及position古掏、limit兩個屬性损话,這種調(diào)整比較微妙,不是太好理解,舉一個簡單例子:首先丧枪,創(chuàng)建緩沖區(qū)光涂。剛開始,緩沖區(qū)處于寫模式拧烦。position為0忘闻,limit為最大容量。然后恋博,向緩沖區(qū)寫數(shù)據(jù)齐佳。每寫入一個數(shù)據(jù),position向后面移動一個位置债沮,也就是position的值加1炼吴。假定寫入了5個數(shù),當(dāng)寫入完成后疫衩,position的值為5缺厉。這時,使用(即調(diào)用)flip方法隧土,將緩沖區(qū)切換到讀模式提针。limit的值,先會被設(shè)置成寫模式時的position值曹傀。這里新的limit是5辐脖,表示可以讀取的最大上限是5個數(shù)。同時皆愉,新的position會被重置為0嗜价,表示可以從0開始讀。
? ? ? ?除了前面的3個屬性幕庐,第4個屬性mark(標記)比較簡單久锥。就是相當(dāng)一個暫存屬性,暫時保存position的值异剥,方便后面的重復(fù)使用position值瑟由。下面用一個表格總結(jié)一下Buffer類的4個重要屬性,參見表3-1冤寿。Buffer四個重要屬性的取值說明
4.buffer的重要方法
? ?? allocate()創(chuàng)建緩沖區(qū),put()寫入到緩沖區(qū),flip()翻轉(zhuǎn),Buffer.clear()從讀取模式轉(zhuǎn)換為寫入模式
5.buffer的使用基本步驟
總體來說歹苦,使用JavaNIOBuffer類的基本步驟如下:
(1)使用創(chuàng)建子類實例對象的allocate()方法,創(chuàng)建一個Buffer類的實例對象督怜。
(2)調(diào)用put方法殴瘦,將數(shù)據(jù)寫入到緩沖區(qū)中。
(3)寫入完成后号杠,在開始讀取數(shù)據(jù)前蚪腋,調(diào)用Buffer.flip()方法丰歌,將緩沖區(qū)轉(zhuǎn)換為讀模式。
(4)調(diào)用get方法屉凯,從緩沖區(qū)中讀取數(shù)據(jù)动遭。
(5)讀取完成后,調(diào)用Buffer.clear()或Buffer.compact()方法神得,將緩沖區(qū)轉(zhuǎn)換為寫入模式厘惦。
本資料收集于Netty、Redis哩簿、Zookeeper高并發(fā)實戰(zhàn),希望大家購買正版圖書