linugb118--java space

          Java

          Java NIO---buffer部分

          Java NIO---buffer部分

          最近想建一個網絡傳輸的平臺,查看到了Jboss 的Netty,而他們核心的傳輸是用了JDK 1.4以后的
          NIO特性,因此借機會學習一下NIO
          NIO主要有下面幾大部分

          Buffer:Io的操作少不了緩存,通過Buffer能大大提高傳輸的效率,同樣NIO中也有Buffer的這部分
          Buffer針對數據類型有相應的子類,他們都是繼承Buffer class
          比如CharBuffer,IntBuffer等等
          需要說明的子類MappedByteBuffer 通過命名可以看出這個MappedByteBuffer有mapped+byte+Buffer組成
          據我理解 這么mapped 是指memory-mapped
          這里解釋一下memory-mapped, 以為我們說的buffer 可能就是指物理上的內存,包括jdk 以前的io
          一般情況下,buffer指物理上的內存沒什么問題,可以物理內存畢竟比較有限,當需要很大buffer存放數據的時候
          物理內存就不夠,那么就引出一個虛擬內存的概念,就像現在的os 一樣,也有虛擬內存的概念,虛擬內存本質上
          是存在硬盤上的,只是物理內存存放的不是具體的數據而是虛擬內存上的地址,而具體的數據則是在虛擬內存上,這樣
          物理內存只是存放很多地址,這樣就大大增加了buffer的size。當然如果你buffer的數據很小,也可以知道放入物理內存
          因此我認為 這個memory-mapped 是指的用虛擬內存的哪種緩存模式

          A.Buffer的 attribute
          1.Capacity:buffer的大小,一個buffer按照某個Capacity創建后就不能修改
          2.Limit:用了多少buffer
          3.Position:指針,獲取下一個元素的位置,操作get(),put(),這個position會自動更新(和iterator相似)
          4.Mark:被標記的指針位置 通過mark()操作可以使mark = position 通過reset() 可以使position = mark

          上面這幾個屬性應該符合下面條件
          0 <= mark <= position <= limit <= capacity


          B. fill:插入數據
          用put() 方法可以插入一段數據 但是這個時候postion 在插入這段數據的尾部

          C. flip:彈出數據
          因為上面寫入數據后,指針在尾部不是從0開始,那么我們需要
          buffer.limit(buffer.position( )).position(0);
          將limit 設置為當前的postion,limit 可以告訴方法這段數據什么時候結束,而具體可以調用方法
          hasRemaining( ) 來判斷是否數據結束。

          同時將當前指針設置為0
          NIO 提供了方法buffer.flip()完成上面的動作

          另外方法rewind( )和flip相似 只是區別在于flip要修改limit,而rewind不修改limit
          rewind 用處可以在已經flip后,還能重讀這段數據

          Buffer不是線程安全的,如果你想要多線程同時訪問,那么需要用synchronization

          D. Mark:讓buffer記住某個指針,已備后面之用。
          調用mark()就能將當前指針mark住
          而調用reset()就能將當前指針回到mark了的指針位置,如果mark未定義,那么調用reset就會報InvalidMarkException
          此外rewind( ), clear( ), and flip( )這些操作將會拋棄mark,這樣clear()和reset()區別
          clear表示清空buffer 而reset表示能將當前指針回到mark了的指針位置

          E:Comparing:buffer 也是java的object sub class,所有buffer也能對象進行比較
          public abstract class ByteBuffer
          extends Buffer implements Comparable
          {
          // This is a partial API listing
          public boolean equals (Object ob)
          public int compareTo (Object ob)
          }

          兩個buffer 認為相等,需要具備下面條件
          1.buffer 類型相同
          2.buffer里面保留的元素數量相同,buffer capacities不需要相同,這里需要注意保留的元素是指有效的元素,不是指buffer里面有的元素。
          其實就從position到limit這段的元素,當然當前的postion和limit值都可以不相同,但這段數據要相同
          3.remaining data 的數據順序要相同,可以通過get()來循環獲取出來后判斷每個element都相同

          如果同時符合上面三個條件,那么就表示buffer object 相等

          F:Bulk Moves
          如何在buffer中大塊的數據移動,對性能起到關鍵作用
          他的做法是get的時候,將一塊數據取出放入數組里面,這樣比起循環get()一個byte要效率高多了,那么對于塊狀數據總是有個指定的長度
          這個長度就是指定數組的長度
          public CharBuffer get (char [] dst, int offset, int length)
          這里就是length。
          如果只有參數為數組buffer.get (myArray);
          那么其實也是指定了長度,只是長度為數組的長度,上面的語句等同于
          buffer.get (myArray, 0, myArray.length);
          針對上面,有可能buffer的data 小于myArray.length,這個時候如果取buffer 那么會報錯
          所以需要下面的寫法
           char [] bigArray = new char [1000];
           // Get count of chars remaining in the buffer
           int length = buffer.remaining( );
           // Buffer is known to contain < 1,000 chars
           buffer.get (bigArrray, 0, length);
           // Do something useful with the data
           processData (bigArray, length);
           這是buffer<length
           如果buffer>length 那需要loop:
           char [] smallArray = new char [10];
           while (buffer.hasRemaining( )) {
           int length = Math.min (buffer.remaining( ), smallArray.length);
           buffer.get (smallArray, 0, length);
           processData (smallArray, length);
           }

          同樣操作put是將array中的數據放入buffer,他同樣有上面length的問題,需要用remaining來判斷

          G:創建Buffer: buffer class 不能直接new創建,他們都是abstract class,但是他們都有static factory,通過factory可以創建instances
          比如
          public abstract class CharBuffer
          extends Buffer implements CharSequence, Comparable
          {
          // This is a partial API listing
          public static CharBuffer allocate (int capacity)
          public static CharBuffer wrap (char [] array)
          public static CharBuffer wrap (char [] array, int offset,
          int length)
          public final boolean hasArray( )
          public final char [] array( )
          public final int arrayOffset( )
          }

          可以通過allocation或者wrapping來創建buffer
          Alloction:允許分配私有buffer
          CharBuffer charBuffer = CharBuffer.allocate (100);
          wrapping:不允許分配私有buffer,顯性提供存儲
          char [] myArray = new char [100];
          CharBuffer charbuffer = CharBuffer.wrap (myArray);

          而myArray  叫做buffer的backing array
          通過hasArray( ) 判斷buffer是否存在backing array
          如果為true,可通過array()得到array的引用

          H:Duplicating Buffers  復制buffer
          Duplicat() 創建一個和原來一樣的新的buffer,他們都有各自的postion,limit,mark, 但是共享同樣的數據,也就是說任何一個buffer被修改了
          他們看到的數據也就修改了。創建的新buffer繼承了老buffer的屬性,比如如果老buffer為readonly,那么新的也是readonly
          asReadOnlyBuffer( ) 和Duplicat()相似,只是區別asReadOnlyBuffer( ) 創建的buffer總是readonly
          slice() 和Duplicat()也相似,不同之處在于slice() 將修改buffer的capacity=(limit - position),同時新buffer以老buffer的當前postion作為開始
          指針。

          I:Byte Buffers 可以獲取不同類型的buffer,另外byte本身也能排序

          J:Direct Buffers: 對于操作系統來說,內存存儲的數據不一定是連續的。而Direct buffer直接用于和io設備進行交互,對于io設備操作的buffer只能是
          direct buffer,如果是nondirect ByteBuffer需要寫入設備,那么他首先是創建一個臨時的direct byteBuffer,然后將內容考入這個臨時direct buffer,
          接著進行底層的io操作,完成io操作后,臨時buffer將被垃圾回收。
          ByteBuffer.allocateDirect()創建direct buffer,isDirect( )則判斷buffer是否是direct buffer

          K:View Buffers  當一堆數據被收到后需要先查看他,然后才能確定是send還是怎么處理,這個時候就要引入View buffer
          View Buffer擁有自己的屬性,比如postion,limit,mark,但是他是和初始buffer共享數據的,這個和duplicated,sliced相似,但是view Buffer
          能將raw bytes 映射為指定的基礎類型buffer,這個也是查看的具體內容了,我們也可以認為是byte buffer向其他基礎類型buffer的轉換

          public abstract class ByteBuffer
          extends Buffer implements Comparable
          {
          // This is a partial API listing
          public abstract CharBuffer asCharBuffer( );
          public abstract ShortBuffer asShortBuffer( );
          public abstract IntBuffer asIntBuffer( );
          public abstract LongBuffer asLongBuffer( );
          public abstract FloatBuffer asFloatBuffer( );
          public abstract DoubleBuffer asDoubleBuffer( );
          }

           

           

           

           

           

           

           

           

           

           

          posted on 2010-09-01 16:01 linugb118 閱讀(1722) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

          My Links

          Blog Stats

          常用鏈接

          留言簿(1)

          隨筆檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 分宜县| 宝坻区| 佛山市| 新源县| 安仁县| 榆社县| 大兴区| 宁阳县| 体育| 嵩明县| 林州市| 涡阳县| 锦州市| 哈巴河县| 霍城县| 福清市| 股票| 清流县| 栾城县| 卫辉市| 昭通市| 明水县| 威信县| 漠河县| 泸溪县| 海兴县| 华安县| 广宁县| 文昌市| 会泽县| 敦煌市| 安溪县| 逊克县| 竹山县| 昌邑市| 上栗县| 锡林郭勒盟| 万载县| 元氏县| 嵩明县| 兰西县|