NIO(一)——Buffer

                                    NIO(一)——Buffer

  •     NIO簡介
    • NIO即New IO,是用來代替標準IO的,提供了與標準IO完全不同傳輸方式。
    • 核心:通道(Channel)和緩衝區(Buffer)和選擇器(Selectors),Channel負責傳輸,Buffer負責存儲
  • 與標準IO的區別
    • 標準IO是面向字節流的,NIO是面向緩衝區的
    • 標準IO是阻塞IO,NIO是非阻塞IO
  1.   當線程從通道讀取數據到緩衝區時,線程還是可以進行其他事情。當數據被寫入到緩衝區時,線程可以繼續處理它。從緩衝區寫入通道也類似。
NIO具有選擇器Selectors
  1. 選擇器用於監聽多個通道的事件(比如:連接打開,數據到達)。因此,單個的線程可以監聽多個數據通道
  • 緩衝區Buffer
      • 在Java NIO中負責數據的存取。緩衝區本質上是一塊可以寫入數據,然後可以從中讀取數據的內存。這塊內存被包裝成NIO Buffer對象,並提供了一組方法,用來方便的訪問該塊內存。
      • 根據數據類型的不同,提供了不同類型的緩衝區(boolean除外):
    1. ByteBuffer
    2. ShortBuffer
    3. IntBuffer
    4. LongBuffer
    5. FloatBuffer
    6. DoubleBuffer
    7. CharBuffer
  • 上述緩衝區的管理方式幾乎一致,通過allocate()獲取緩衝區:
  1. ByteBuffer buf = ByteBuffer.allocate(1024);
緩衝區存儲數據的兩個核心方法:
  1. put():存數據到緩衝區
  2. get():從緩衝區取數據
緩衝區中的核心屬性:
  1. capacity:容量,表示緩衝區中最大存儲數據的容量,一旦聲明不可改變
  2. limit:界限,表示緩存區衝可以操作數據的大小。limit後的數據不能進行讀寫(讀和寫操作含義不同)
  3. position:位置,表示緩衝區中正在操作的數據的位置
  4. mark:標記,表示記錄當前position的位置,可以通過reset()恢復到mark的位置
  5. 0<=mark<=position<=limit<=capacity
  • 方法:
  •   
    • flid()方法:在切換讀寫模式的時候必須調用flid()方法
    1. buf.flip();
    2. flip()方法:
 
                  public final Buffer flip() {
                            limit = position;
                            position = 0;
                                mark = -1;
                            return this;
                        }

  • rewind()方法:
  1.       可重複讀數據,將position置0,limit不變
  2.   public final Buffer rewind() {
            position = 0;
            mark = -1;
            return this;
        }


clear()與compact()方法:
  • 一旦讀完緩衝區中的數據,需要讓緩衝區準備好再次被寫入。可以通過clear()或compact方法來完成。
  • 如果調用的是clear()方法,position將被置0,limit被設置爲capacity的值。即緩衝區被清空。但緩衝區中的數據並未被清除。
  • 如果緩衝區中有一些未讀的數據,調用clean()方法,數據將“被遺忘”。
  • 如果緩衝區中有一些未讀的數據,且後續還需要這些數據,但此時想先寫些數據,就使用compact()方法。compact()方法將所有未讀的數據拷貝到Buffer起始處,然後將position設到最後一個未讀元素後面,limit=capacity。
  •    public final Buffer clear() {
            position = 0;
            limit = capacity;
            mark = -1;
            return this;
        }
       public abstract ByteBuffer compact();
    • 直接緩衝區與非直接緩衝區:
    1. 非直接緩衝區:通過allocate()方法分配緩衝區,將緩衝區建立在JVM內存中
    2.  public static ByteBuffer allocate(int capacity) {
            	if (capacity < 0)
                	throw new IllegalArgumentException();
           	return new HeapByteBuffer(capacity, capacity);
          }
      HeapByteBuffer(int cap, int lim) {   
        	super(-1, 0, lim, cap, new byte[cap], 0);
          }
      ByteBuffer(int mark, int pos, int lim, int cap, byte[] hb, int offset){
          			 super(mark, pos, lim, cap);
         			 this.hb = hb;
            			this.offset = offset;
          }

    • 直接緩衝區:
    • 通過allocateDirect()方法分配直接緩衝區,將緩衝區建立在物理內存中。可以提高效率        
     public static ByteBuffer allocateDirect(int capacity) {
         		return new DirectByteBuffer(capacity);
      			 }
     DirectByteBuffer(int cap) {      
            super(-1, 0, cap, cap);
            boolean pa = VM.isDirectMemoryPageAligned();
              //調用直接內存方法進行分配
            int ps = Bits.pageSize();
            long size = Math.max(1L, (long)cap + (pa ? ps : 0));
            Bits.reserveMemory(size, cap);
    
            long base = 0;
            try {
                base = unsafe.allocateMemory(size);
            } catch (OutOfMemoryError x) {
                Bits.unreserveMemory(size, cap);
                throw x;
            }
            unsafe.setMemory(base, size, (byte) 0);
            if (pa && (base % ps != 0)) {
                address = base + ps - (base & (ps - 1));
            } else {
                address = base;
            }
            cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
            att = null;
        }







發佈了38 篇原創文章 · 獲贊 4 · 訪問量 5883
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章