<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 312, 文章 - 14, 評論 - 1393, 引用 - 0
    數據加載中……

    Java網絡編程從入門到精通(33):非阻塞I/O的緩沖區(Buffer)

    本文為原創,如需轉載,請注明作者和出處,謝謝!

    上一篇:Java網絡編程從入門到精通(32):一個非阻塞I/O的例子

    如果將同步I/O方式下的數據傳輸比做數據傳輸的零星方式(這里的零星是指在數據傳輸的過程中是以零星的字節方式進行的),那么就可以將非阻塞I/O方式下的數據傳輸比做數據傳輸的集裝箱方式(在字節和低層數據傳輸之間,多了一層緩沖區,因此,可以將緩沖區看做是裝載字節的集裝箱)。大家可以想象,如果我們要運送比較少的貨物,用集裝箱好象有點不太合算,而如果要運送上百噸的貨物,用集裝箱來運送的成本會更低。在數據傳輸過程中也是一樣,如果數據量很小時,使用同步I/O方式會更適合,如果數據量很大時(一般以G為單位),使用非阻塞I/O方式的效率會更高。因此,從理論上說,數據量越大,使用非阻塞I/O方式的單位成本就會越低。產生這種結果的原因和緩沖區的一些特性有著直接的關系。在本節中,將對緩沖區的一些主要特性進行講解,使讀者可以充分理解緩沖區的概念,并能通過緩沖區來提高程序的執行效率。

    創建緩沖區

    Java提供了七個基本的緩沖區,分別由七個類來管理,它們都可以在java.nio包中找到。這七個類如下所示:

    •  ByteBuffer   
    • ShortBuffer
    • IntBuffer
    • CharBuffer
    • FloatBuffer
    • DoubleBuffer
    • LongBuffer

    這七個類中的方法類似,只是它們的返回值或參數和相應的簡單類型相對應,如ByteBuffer類的get方法返回了byte類型的數據,而put方法需要一個byte類型的參數。在CharBuffer類中的getput方法返回和傳遞的數據類型就是char。這七個類都沒有public構造方法,因此,它們不能通過new來創建相應的對象實例。這些類都可以通過兩種方式來創建相應的對象實例。

    1.        通過靜態方法allocate來創建緩沖區。

    這七類都有一個靜態的allocate方法,通過這個方法可以創建有最大容量限制的緩沖區對象。allocate的定義如下:

    ByteBuffer類中的allocate方法:

    public static ByteBuffer allocate(int capacity)

    IntBuffer類中的allocate方法:

    public static IntBuffer allocate(int capacity)

    其他五個緩沖區類中的allocate 方法定義和上面的定義類似,只是返回值的類型是相應的緩沖區類。

    allocate方法有一個參數capacity,用來指定緩沖區容量的最大值。capacity的不能小于0,否則會拋出一個IllegalArgumentException異常。使用allocate來創建緩沖區,并不是一下子就分配給緩沖區capacity大小的空間,而是根據緩沖區中存儲數據的情況來動態分配緩沖區的大小(實際上,在低層Java采用了數據結構中的堆來管理緩沖區的大小),因此,這個capacity可以是一個很大的值,如1024*10241M)。allocate的使用方法如下:

    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
    IntBuffer intBuffer 
    = IntBuffer.allocate(1024);

        在使用allocate創建緩沖區時應用注意,capacity的含義隨著緩沖區的不同而不同。如創建字節緩沖區時,capacity指的是字節數。而在創建整型(int)緩沖區時,capacity指的是int型值的數目,如果轉換成字數,capacity的值應該乘4。如上面代碼中的intBuffer緩沖區最大可容納的字節數是1024*4 = 4096個。

    2.        通過靜態方法wrap來創建緩沖區。

    使用allocate方法可以創建一個空的緩沖區。而wrap方法可以利用已經存在的數據來創建緩沖區。wrap方法可以將數組直接轉換成相應類型的緩沖區。wrap方法有兩種重載形式,它們的定義如下:

    ByteBuffer類中的wrap方法:

    public static ByteBuffer wrap(byte[] array)
    public static ByteBuffer wrap(byte[] array, int offset, int length)

    IntBuffer類中的wrap方法:

    public static IntBuffer wrap(byte[] array)
    public static IntBuffer wrap(byte[] array, int offset, int length)

    其他五個緩沖區類中的wrap 方法定義和上面的定義類似,只是返回值的類型是相應的緩沖區類。

    wrap方法中的array參數是要轉換的數組(如果是其他的緩沖區類,數組的類型就是相應的簡單類型,如IntBuffer類中的wrap方法的array就是int[]類型)。offset是要轉換的子數組的偏移量,也就是子數組在array中的開始索引。length是要轉換的子數組的長度。利用后兩個參數可以將array數組中的一部分轉換成緩沖區對象。它們的使用方法如下:

    byte[] myByte = new byte[] { 123 };
    int[] myInt = new int[] { 1234 };
    ByteBuffer byteBuffer 
    = ByteBuffer.wrap(myByte);
    IntBuffer intBuffer 
    = IntBuffer.wrap(myInt, 12);

    可以通過緩沖區類的capacity方法來得到緩沖區的大小。capacity方法的定義如下:

    public final int capacity()

    如果使用allocate方法來創建緩沖區,capacity方法的返回值就是capacity參數的值。而使用wrap方法來創建緩沖區,capacity方法的返回值是array數組的長度,但要注意,使用wrap來轉換array的字數組時,capacity的長度仍然是原數組的長度,如上面代碼中的intBuffer緩沖區的capacity值是4,而不是2

    除了可以將數組轉換成緩沖區外,也可以通過緩沖區類的array方法將緩沖區轉換成相應類型的數組。IntBuffer類的array方法的定義方法如下(其他緩沖區類的array的定義類似):

    public final int[] array()

        下面的代碼演示了如何使用array方法將緩沖區轉換成相應類型的數組。


    int[] myInt = new int[] { 123456 };
    IntBuffer intBuffer 
    = IntBuffer.wrap(myInt, 13);
    for (int v : intBuffer.array())
        System.out.print(v 
    + " ");

    在執行上面代碼后,我們發現輸出的結果是1 2 3 4 5 6,而不是2 3 4。這說明在將子數組轉換成緩沖區的過程中實際上是將整個數組轉換成了緩沖區,這就是用wrap包裝子數組后,capacity的值仍然是原數組長度的真正原因。在使用array方法時應注意,在以下兩種緩沖區中不能使用array方法:

    • 只讀的緩沖區

    如果使用只讀緩沖區的array方法,將會拋出一個ReadOnlyBufferException異常。

    • 使用allocateDirect方法創建的緩沖區

    如果調用這種緩沖區中的array方法,將會拋出一個UnsupportedOperationException異常。

    可以通過緩沖區類的hasArray方法來判斷這個緩沖區是否可以使用array方法,如果返回true,則說明這個緩沖區可以使用array方法,否則,使用array方法將會拋出上述的兩種異常之一。

    注意: 使用array方法返回的數組并不是緩沖區數據的副本。被返回的數組實際上就是緩沖區中的數據,也就是說,array方法只返回了緩沖區數據的引用。當數組中的數據被修改后,緩沖區中的數據也會被修改,返之也是如此。關于這方面內容將在下一節“讀寫緩沖區中的數據”中詳細講解。

    在上述的七個緩沖區類中,ByteBuffer類和CharBuffer類各自還有另外一種方法來創建緩沖區對象。

    l         ByteBuffer

    可以通過ByteBuffer類的allocateDirect方法來創建ByteBuffer對象。allocateDirect方法的定義如下:

    public static ByteBuffer allocateDirect(int capacity)

    使用allocateDirect方法可以一次性分配capacity大小的連續字節空間。通過allocateDirect方法來創建具有連續空間的ByteBuffer對象雖然可以在一定程度上提高效率,但這種方式并不是平臺獨立的。也就是說,在一些操作系統平臺上使用allocateDirect方法來創建ByteBuffer對象會使效率大幅度提高,而在另一些操作系統平臺上,性能會表現得非常差。而且allocateDirect方法需要較長的時間來分配內存空間,在釋放空間時也較慢。因此,在使用allocateDirect方法時應謹慎。

    通過isDirect方法可以判斷緩沖區對象(其他的緩沖區類也有isDirect方法,因為,ByteBuffer對象可以轉換成其他的緩沖區對象,這部分內容將在后面講解)是用哪種方式創建的,如果isDirect方法返回true,則這個緩沖區對象是用allocateDirect方法創建的,否則,就是用其他方法創建的緩沖區對象。

    l         CharBuffer

    我們可以發現,上述的七種緩沖區中并沒有字符串緩沖區,而字符串在程序中卻是最常用的一種數據類型。不過不要擔心,雖然java.nio包中并未提供字符串緩沖區,但卻可以將字符串轉換成字符緩沖區(就是CharBuffer對象)。在CharBuffer類中的wrap方法除了上述的兩種重載形式外,又多了兩種重載形式,它們的定義如下:

    public static CharBuffer wrap(CharSequence csq)
    public static CharBuffer wrap(CharSequence csq, int start, int end)

    其中csq參數表示要轉換的字符串,但我們注意到csq的類型并不是String,而是CharSequenceCharSequenceJava中四個可以表示字符串的類的父類,這四個類是StringStringBufferStringBuilderCharBuffer(大家要注意,StringBuffer和本節講的緩沖區類一點關系都沒有,這個類在java.lang包中)。也就是說,CharBuffer類的wrap方法可以將這四個類的對象轉換成CharBuffer對象。

    另外兩個參數startend分別是子字符串的開始索引和結束索引的下一個位置,如將字符串"1234"中的"23" 轉換成CharBuffer對象的語句如下:

    CharBuffer cb = CharBuffer.wrap("1234"13);

        下面的代碼演示了如何使用wrap方法將不同形式的字符串轉換成CharBuffer對象。

    StringBuffer stringBuffer = new StringBuffer("通過StringBuffer創建CharBuffer對象");
    StringBuilder stringBuilder 
    = new StringBuilder("通過StringBuilder創建CharBuffer對象");
    CharBuffer charBuffer1 
    = CharBuffer.wrap("通過String創建CharBuffer對象");
    CharBuffer charBuffer2 
    = CharBuffer.wrap(stringBuffer);
    CharBuffer charBuffer3 
    = CharBuffer.wrap(stringBuilder);
    CharBuffer charBuffer4 
    = CharBuffer.wrap(charBuffer1, 13);

    下一篇:Java網絡編程從入門到精通(34):讀寫緩沖區中的數據---使用get和put方法按順序讀寫單個數據





    Android開發完全講義(第2版)(本書版權已輸出到臺灣)

    http://product.dangdang.com/product.aspx?product_id=22741502



    Android高薪之路:Android程序員面試寶典 http://book.360buy.com/10970314.html


    新浪微博:http://t.sina.com.cn/androidguy   昵稱:李寧_Lining

    posted on 2009-08-31 08:49 銀河使者 閱讀(3225) 評論(0)  編輯  收藏 所屬分類: java 原創網絡編程

    主站蜘蛛池模板: 亚洲国产成人VA在线观看| 少妇无码一区二区三区免费| 免费A级毛片无码免费视| 一区二区三区亚洲| 国产无遮挡裸体免费视频在线观看| 亚洲av区一区二区三| 看亚洲a级一级毛片| 免费国产成人高清视频网站| 韩国亚洲伊人久久综合影院| 精品少妇人妻AV免费久久洗澡| 亚洲精品国产首次亮相| 免费看片A级毛片免费看| 亚洲爆乳无码精品AAA片蜜桃| 免费黄色网址入口| 国产亚洲精品美女2020久久| 亚洲AⅤ视频一区二区三区| 视频免费1区二区三区| 国产亚洲精品高清在线| 你懂的免费在线观看网站| 亚洲精品mv在线观看| 亚洲免费网站观看视频| 亚洲精品动漫免费二区| 成人伊人亚洲人综合网站222| 丁香六月婷婷精品免费观看| 亚洲日韩中文无码久久| 免费黄网站在线看| 亚洲国产精品无码久久久| 在线免费观看毛片网站| 一区二区在线视频免费观看| 亚洲免费在线播放| 好男人视频在线观看免费看片| 日韩色视频一区二区三区亚洲| 亚洲午夜未满十八勿入网站2| 成人久久免费网站| 亚洲欧洲日产国产最新| 国产传媒在线观看视频免费观看 | 亚洲乱码一二三四区麻豆| 永久免费观看的毛片的网站| 中文在线免费视频| 亚洲一区二区三区在线观看蜜桃 | 亚洲日韩乱码中文无码蜜桃臀|