nio buffer用法

nio buffer 用法

NIO的Buffer(緩沖區(qū))本質(zhì)上是一個(gè)內(nèi)存塊,既可以寫(xiě)入數(shù)據(jù),也可以從中讀取數(shù)據(jù)。NIO的Buffer類(lèi),是一個(gè)抽象類(lèi),位于java.nio包中,其內(nèi)部是一個(gè)內(nèi)存塊(數(shù)組)。NIO的Buffer與普通的內(nèi)存塊(Java數(shù)組)不同的是:NIOBuffer對(duì)象,提供了一組更加有效的方法,用來(lái)進(jìn)行寫(xiě)入和讀取的交替訪問(wèn)。需要強(qiáng)調(diào)的是:Buffer類(lèi)是一個(gè)非線程安全類(lèi).


1. Buffer類(lèi)Buffer類(lèi)是一個(gè)抽象類(lèi),對(duì)應(yīng)于Java的主要數(shù)據(jù)類(lèi)型,在NIO中有8種緩沖區(qū)類(lèi),分別如下
:ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer、ShortBuffer、MappedByteBuffer。前7種Buffer類(lèi)型,覆蓋了能在IO中傳輸?shù)乃械腏ava基本數(shù)據(jù)類(lèi)型。第8種類(lèi)型MappedByteBuffer是專門(mén)用于內(nèi)存映射的一種ByteBuffer類(lèi)型。實(shí)際上,使用最多的還是ByteBuffer二進(jìn)制字節(jié)緩沖區(qū)類(lèi)型,后面會(huì)看到。
2.capacity屬性Buffer類(lèi)的capacity屬性,表示內(nèi)部容量的大小。
? ? ? ?一旦寫(xiě)入的對(duì)象數(shù)量超過(guò)了capacity容量,緩沖區(qū)就滿了,不能再寫(xiě)入了。Buffer類(lèi)的capacity屬性一旦初始化,就不能再改變。原因是什么呢?Buffer類(lèi)的對(duì)象在初始化時(shí),會(huì)按照capacity分配內(nèi)部的內(nèi)存。在內(nèi)存分配好之后,它的大小當(dāng)然就不能改變了。再?gòu)?qiáng)調(diào)一下,capacity容量不是指內(nèi)存塊byte[]數(shù)組的字節(jié)的數(shù)量。capacity容量指的是寫(xiě)入的數(shù)據(jù)對(duì)象的數(shù)量。前面講到,Buffer類(lèi)是一個(gè)抽象類(lèi),Java不能直接用來(lái)新建對(duì)象。使用的時(shí)候,必須使用Buffer的某個(gè)子類(lèi),例如使用DoubleBuffer,則寫(xiě)入的數(shù)據(jù)是double類(lèi)型,如果其capacity是100,那么我們最多可以寫(xiě)入100個(gè)double數(shù)據(jù)。
3.position屬性Buffer類(lèi)的position屬性,表示當(dāng)前的位置。
????????position屬性與緩沖區(qū)的讀寫(xiě)模式有關(guān)。在不同的模式下,position屬性的值是不同的。當(dāng)緩沖區(qū)進(jìn)行讀寫(xiě)的模式改變時(shí),position會(huì)進(jìn)行調(diào)整。
????在寫(xiě)入模式下,position的值變化規(guī)則如下:
(1)在剛進(jìn)入到寫(xiě)模式時(shí),position值為0,表示當(dāng)前的寫(xiě)入位置為從頭開(kāi)始。
(2)每當(dāng)一個(gè)數(shù)據(jù)寫(xiě)到緩沖區(qū)之后,position會(huì)向后移動(dòng)到下一個(gè)可寫(xiě)的位置。
(3)初始的position值為0,最大可寫(xiě)值position為limit–1。當(dāng)position值達(dá)到limit時(shí),緩沖區(qū)就已經(jīng)無(wú)空間可寫(xiě)了。
在讀模式下,position的值變化規(guī)則如下:
(1)當(dāng)緩沖區(qū)剛開(kāi)始進(jìn)入到讀模式時(shí),position會(huì)被重置為0。
(2)當(dāng)從緩沖區(qū)讀取時(shí),也是從position位置開(kāi)始讀。讀取數(shù)據(jù)后,position向前移動(dòng)到下一個(gè)可讀的位置。(3)position最大的值為最大可讀上限limit,當(dāng)position達(dá)到limit時(shí),表明緩沖區(qū)已經(jīng)無(wú)數(shù)據(jù)可讀。起點(diǎn)在哪里呢?當(dāng)新建一個(gè)緩沖區(qū)時(shí),緩沖區(qū)處于寫(xiě)入模式,這時(shí)是可以寫(xiě)數(shù)據(jù)的。數(shù)據(jù)寫(xiě)入后,如果要從緩沖區(qū)讀取數(shù)據(jù),這就要進(jìn)行模式的切換,可以使用(即調(diào)用)flip翻轉(zhuǎn)方法,將緩沖區(qū)變成讀取模式。在這個(gè)flip翻轉(zhuǎn)過(guò)程中,position會(huì)進(jìn)行非常巨大的調(diào)整,具體的規(guī)則是:position由原來(lái)的寫(xiě)入位置,變成新的可讀位置,也就是0,表示可以從頭開(kāi)始讀。flip翻轉(zhuǎn)的另外一半工作,就是要調(diào)整limit屬性。
3.limit屬性Buffer類(lèi)的limit屬性,表示讀寫(xiě)的最大上限。
????????limit屬性,也與緩沖區(qū)的讀寫(xiě)模式有關(guān)。在不同的模式下,limit的值的含義是不同的。在寫(xiě)模式下,limit屬性值的含義為可以寫(xiě)入的數(shù)據(jù)最大上限。在剛進(jìn)入到寫(xiě)模式時(shí),limit的值會(huì)被設(shè)置成緩沖區(qū)的capacity容量值,表示可以一直將緩沖區(qū)的容量寫(xiě)滿。在讀模式下,limit的值含義為最多能從緩沖區(qū)中讀取到多少數(shù)據(jù)。
一般來(lái)說(shuō),是先寫(xiě)入再讀取。當(dāng)緩沖區(qū)寫(xiě)入完成后,就可以開(kāi)始從Buffer讀取數(shù)據(jù),可以使用flip翻轉(zhuǎn)方法,這時(shí),limit的值也會(huì)進(jìn)行非常大的調(diào)整。具體如何調(diào)整呢?將寫(xiě)模式下的position值,設(shè)置成讀模式下的limit值,也就是說(shuō),將之前寫(xiě)入的最大數(shù)量,作為可以讀取的上限值。在flip翻轉(zhuǎn)時(shí),屬性的調(diào)整,將涉及position、limit兩個(gè)屬性,這種調(diào)整比較微妙,不是太好理解,舉一個(gè)簡(jiǎn)單例子:首先,創(chuàng)建緩沖區(qū)。剛開(kāi)始,緩沖區(qū)處于寫(xiě)模式。position為0,limit為最大容量。然后,向緩沖區(qū)寫(xiě)數(shù)據(jù)。每寫(xiě)入一個(gè)數(shù)據(jù),position向后面移動(dòng)一個(gè)位置,也就是position的值加1。假定寫(xiě)入了5個(gè)數(shù),當(dāng)寫(xiě)入完成后,position的值為5。這時(shí),使用(即調(diào)用)flip方法,將緩沖區(qū)切換到讀模式。limit的值,先會(huì)被設(shè)置成寫(xiě)模式時(shí)的position值。這里新的limit是5,表示可以讀取的最大上限是5個(gè)數(shù)。同時(shí),新的position會(huì)被重置為0,表示可以從0開(kāi)始讀。
? ? ? ?除了前面的3個(gè)屬性,第4個(gè)屬性mark(標(biāo)記)比較簡(jiǎn)單。就是相當(dāng)一個(gè)暫存屬性,暫時(shí)保存position的值,方便后面的重復(fù)使用position值。下面用一個(gè)表格總結(jié)一下Buffer類(lèi)的4個(gè)重要屬性,參見(jiàn)表3-1。Buffer四個(gè)重要屬性的取值說(shuō)明

4.buffer的重要方法
? ?? allocate()創(chuàng)建緩沖區(qū),put()寫(xiě)入到緩沖區(qū),flip()翻轉(zhuǎn),Buffer.clear()從讀取模式轉(zhuǎn)換為寫(xiě)入模式

5.buffer的使用基本步驟
總體來(lái)說(shuō),使用JavaNIOBuffer類(lèi)的基本步驟如下:
(1)使用創(chuàng)建子類(lèi)實(shí)例對(duì)象的allocate()方法,創(chuàng)建一個(gè)Buffer類(lèi)的實(shí)例對(duì)象。
(2)調(diào)用put方法,將數(shù)據(jù)寫(xiě)入到緩沖區(qū)中。
(3)寫(xiě)入完成后,在開(kāi)始讀取數(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)換為寫(xiě)入模式。

本資料收集于Netty、Redis、Zookeeper高并發(fā)實(shí)戰(zhàn),希望大家購(gòu)買(mǎi)正版圖書(shū)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容