Java NIO之緩衝區

來源:互聯網
上載者:User

標籤:控制   不可   code   問題   目標   核心空間   system   影響   合成   

  • 簡介
    • IO概念
      • 緩衝區操作
      • 虛擬記憶體
      • 檔案IO
      • 流IO
  • 緩衝區
    • Buffer屬性
    • Buffer資料填充、翻轉、釋放、壓縮、標記
    • Buffer比較
    • Buffer批量移動
    • 複製緩衝區
  • 位元組緩衝區
    • 直接緩衝區
    • 其他緩衝區
簡介

幾個IO事實:

  1. 影響應用程式執行效率的限定因素,往往非處理速率,而是IO
  2. OS要移動大塊資料,往往是在DMA協助下完成,而JVM的IO操作往往是小塊資料,有了NIO,可改變這種情況
  3. JDK1.4,java.nio提供了一套新的抽象用於IO處理
IO概念 緩衝區操作

進程執行IO操作,要麼把緩衝區的資料排幹(read),要麼用資料把緩衝區填滿(write)。
進程使用read()系統調用,要求其緩衝區需要被填滿,核心隨機向磁碟控制硬體發出命令,通過DMA(無需主CPU協助)講資料寫入核心記憶體緩衝區,一旦磁碟控制卡把緩衝區裝滿,核心即把資料從核心空間的臨時緩衝區拷貝到進程read()調用時執行的緩衝區。

其中使用者空間和核心空間
使用者空間是常規進程所在地區,如JVM。核心空間是作業系統所在地區,有特別權力,能與裝置控制器通訊,控制使用者地區進程的運行狀態等。總之,所有IO都直接或間接通過核心空間。
硬體不能直接存取使用者空間,硬體裝置操作的是固定大小的資料區塊,而使用者進程請求的可能是任意大小的或非對齊的資料區塊。

虛擬記憶體

使用虛擬位址取代實體記憶體地址,有個兩大類好處,一是多個虛擬位址可知指向同一物理地址,二是虛擬記憶體空間可大於硬體記憶體。

檔案IO

檔案系統與磁碟不同,檔案系統是高層次的抽象,是安排、解釋磁碟或其他隨機存取塊裝置資料的一種獨特方法。
檔案系統資料也會同其他記憶體頁一樣得到快取,對於隨後發生的IO請求,檔案資料的部分或全部可能仍位於實體記憶體中,無需從磁碟讀取。

檔案鎖定:分為共用和獨佔。多個共用鎖定可同時對同一檔案地區發生作用,獨佔鎖要求相關地區不能有其他鎖起作用。

流IO

原理模仿通道,必須順序存取,如控制台裝置、印表機連接埠。

緩衝區

Buffer類是nio構造基礎,一個Buffer對象是固定數量的資料容器,在這裡的資料可悲儲存並在之後用於檢索。可以理解為是I/O操作中資料的中轉站。緩衝區直接為通道(Channel)服務,寫入資料到通道或從通道讀取資料,這樣的操利用緩衝區資料來傳遞就可以達到對資料高效處理的目的。

Buffer屬性

容量capacity:建立時設定,不可改變。
上界limit:不可讀寫。現存元素的計數。
位置position:下一個要被讀或寫元素的索引。
標記mark:一個備忘位置。

Buffer資料填充、翻轉、釋放、壓縮、標記

java.nio.Buffer類是一個抽象類別,不能被執行個體化。Buffer類的直接子類,如ByteBuffer等也是抽象類別,所以也不能被執行個體化。
但是ByteBuffer類提供了靜態Factory 方法來獲得ByteBuffer的執行個體,終於到了show代碼的時候了=。=,如下:

               //初始化        ByteBuffer buffer = ByteBuffer.allocate(1024);        //資料填充        buffer.put((byte) ‘H‘).put((byte) ‘e‘).put((byte) ‘l‘).put((byte) ‘l‘).put((byte) ‘o‘);        System.out.println(buffer.toString());//java.nio.HeapByteBuffer[pos=5 lim=1024 cap=1024]        System.out.println((char) (buffer.get(0)));//H        //資料修改        buffer.put(0, (byte) ‘M‘).put((byte) ‘w‘);        System.out.println(buffer.toString());//java.nio.HeapByteBuffer[pos=6 lim=1024 cap=1024]        System.out.println((char) (buffer.get(0)));//M        //flip將position歸0,將一個待填充狀態的緩衝區翻轉成準備讀出狀態        System.out.println(buffer);//java.nio.HeapByteBuffer[pos=6 lim=1024 cap=1024]        buffer.flip();        //buffer.rewind();//類似flip,但是不影響limit屬性。java.nio.HeapByteBuffer[pos=0 lim=1024 cap=1024]        System.out.println(buffer);//java.nio.HeapByteBuffer[pos=0 lim=6 cap=1024]        //使用hasRemaining()判斷是否達到緩衝區上界        while (buffer.hasRemaining()) {            System.out.print((char) (buffer.get()));        }//Mellow        System.out.println("");        //壓縮,compact丟棄已釋放資料,保留未釋放資料        buffer.compact();        //mark,在某個位置標記,reset( )函數將位置設為當前的標記值。        // 如果標記值未定義,調 用 reset( )將導致 InvalidMarkException 異常。        // 一些緩衝區函數會拋棄已經設定的標記 (rewind( ),clear( ),以及 flip( )總是拋棄標記)。        buffer.position(2).mark();
Buffer比較

比較兩個緩衝區,ByteBuffer已經實現Comparable介面,源碼如下:

 public int compareTo(ByteBuffer that) {        int n = this.position() + Math.min(this.remaining(), that.remaining());        for (int i = this.position(), j = that.position(); i < n; i++, j++) {            int cmp = compare(this.get(i), that.get(j));            if (cmp != 0)                return cmp;        }        return this.remaining() - that.remaining();    }    private static int compare(byte x, byte y) {        return Byte.compare(x, y);    }
Buffer批量移動
        //批量取        byte[] myArray = new byte[1000];        buffer.get(myArray);        //等價於:        buffer.get(myArray, 0, myArray.length);        //批量存        byte[] myString = new byte[1000];        buffer.put(myString);        //等價於:        buffer.put(myString,0,myString.length);
複製緩衝區

使用duplicate()函數可以複製緩衝區,會建立一個新的buffer對象,但並不會複製資料,原始緩衝區和副本都會操作同樣的資料元素。

位元組緩衝區

所有的基礎資料型別 (Elementary Data Type)都有相應的緩衝區類(布爾除外),位元組類型比較特殊,位元組是作業系統和其IO裝置使用的基本類型。
非位元組類型的基本類型,也是由位元組組合成的,比如char2個位元組,int4個位元組,double8個位元組。組合的位元組是有順序的,Java預設的位元組順序是大端位元組順序,參見類ByteOreder。

直接緩衝區

位元組緩衝區可以成為通道所執行IO的源頭或目標,非位元組緩衝區傳遞給通道,會隱含執行複製內容到一個臨時ByteBuffer,所以直接緩衝區是IO的最佳選擇。
通過isDirect()函數,判定緩衝區是否為直接緩衝區。

其他緩衝區

視圖緩衝區,這種視圖對象維持它自己的屬性、容量、位置、上界和標記,但是和原來緩衝區共用資料元素。
CharBuffer charBuffer = byteBuffer.asCharBuffer( );

ByteBuffer類為每一種未經處理資料類型提供了存取和轉化的方法,比如getInt()函數被調用,從當前位置開始的4個位元組會被封裝成一個int類型變數返回。
對於無符號資料,自行實現,注意精度問題。

Java NIO之緩衝區

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.