欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

NIO(一)——Buffer

程序员文章站 2022-05-09 21:23:47
...

                                    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
  • NIO(一)——BufferNIO(一)——Buffer
  • 方法:
  •   
    • 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. NIO(一)——Buffer
    3.  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()方法分配直接缓冲区,将缓冲区建立在物理内存中。可以提高效率        NIO(一)——Buffer
     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;
        }







相关标签: NIO 缓冲区