zoukankan      html  css  js  c++  java
  • 2.Buffer 缓冲区

    /*缓冲区(Buffer)*/

    Buffer 就像一个数组,可以保存多个相同类型的数据。根据数据类型不同(boolean 除外),有以下Buffer常用子类:

    /*ByteBuffer*/(常用) 、CharBuffer 、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer 

    上述Buffer 类,他们都采用相似的方式进行管理数据,只是各自管理的数据类型不同而已。都是通过如下方法获取一个Buffer对象:

      static XxxBuffer allocate(int capacity): 创建一个容量为 capacity 的 XxxBuffer对象



    /*缓存区的基本属性*/

    Buffer中的重要概念:

      1.容量(capacity):表示Buffer 最大数据容量,缓冲区容量不能为负,并且创建后不能修改 (创建Buffer对象时 初始化)


      2.限制(limit):第一个不应该读取或写入的数据的索引,(即位于limit后的数据不可读写)缓冲区的限制 不能为负,并且不能大于其容量


      3.位置(position):下一个要读取或写入的数据的索引。缓冲区的位置不能为负,并且不能大于其限制值

      

      4.标记(mark)与重置(reset):标记也是一个索引,通过Buffer中的 mark() 方法指定Buffer中一个特定的position,之后可以通过调用reset()方法恢复到这个 position


    标记、位置、限制、容量遵循以下不变式:/*0 <= mark <= position <= limit <= capacity*/


    Buffer的常用方法

      Bufffer clear() 清空缓冲区(索引重置为初始状态)并返回对缓冲区的引用(但是缓冲区的数据依然存在,但是出于 “被遗忘” 状态)

      Buffer flip() 将缓冲区的界限设置为当前位置,并将当前位置重置为0 (即准备开始操作缓冲区里面的数据)

    缓冲区的数据操作

      Buffer 所有子类提供了 两个用于数据操作的方法: get() 与 put() 方法


    /*直接与非直接缓冲区*/

      非直接缓冲区:通过allocate() 方法 分配缓冲区,将缓冲区建立在 JVM内存中

      直接缓冲区: 通过 allocateDirect() 方法 分配直接缓冲区,将缓冲区建立在物理内存中,可以提高效率

    字节缓冲区要么是直接的,要么是非直接的。如果是直接字节缓冲区,则Java 虚拟机 会尽最大努力直接在此缓冲区上执行本机 I/O 操作

    即直接缓冲区: 通过过一个 ‘物理内存映射文件’ ,将本来要放在JVM内存中的缓冲区 直接放到 物理内存中

    非直接缓冲区: 将缓冲区 先放到JVM 的内存中,然后通过 copy ,将内容复制到 内核地址空间(物理内存) ,写入磁盘


    直接缓冲区少了一个 copy 的过程,自然速度会更快,但是也有缺点:1.直接在物理内存上开辟和销毁空间的代价很大,2.基本上失去了对缓冲区数据的控制,无法控制其销毁

    所以:仅在直接缓冲区能在程序性能方面带来明显好处时分配他们

      1 /*
      2  * 一、缓冲区(Buffer):在Java NIO中负责数据的存取。缓冲区就是数组。用于存储不同数据类型的数据
      3  *
      4  * 根据数据类型不同 (boolean 除外),提供了相应类型的缓冲区
      5  * ByteBuffer(常用) 、CharBuffer、ShortBuffer等
      6  *
      7  * 上述缓冲区 的 管理方式几乎一致,通过 allocate() 获取缓冲区
      8  * 
      9  * 二、缓冲区存取数据的两个核心方法:
     10  * put():存入 数据到缓冲区
     11  * get():获取缓冲区的数据
     12  * 
     13  * 三、缓冲区的四个核心属性
     14  * 1.capacity : 容量,表示Buffer 最大数据容量,缓冲区容量不能为负,并且创建后不能修改  (创建Buffer对象时 初始化)
     15  * 
     16  * 2.限制(limit):第一个不应该读取或写入的数据的索引,(即位于limit后的数据不可读写)
     17                              缓冲区的限制 不能为负,并且不能大于其容量
     18    3.位置(position):下一个要读取或写入的数据的索引。缓冲区的位置不能为负,并且不能大于其限制值                         
     19     
     20    4.标记(mark)与重置(reset):标记也是一个索引,通过Buffer中的 mark() 方法指定Buffer中一个特定的position,
     21         之后可以通过调用reset()方法恢复到这个 position                             
     22  * 
     23  *  0 <= mark <= position <= limit <= capacity
     24  *  
     25  *  四、直接缓冲区 和 非直接缓冲区
     26  *  非直接缓冲区:通过allocate() 方法 分配缓冲区,将采取建立在 JVM内存中
     27  *  直接缓冲区:通过 allocateDirect() 方法 分配直接缓冲区,将缓冲区建立在物理内存中,可以提高效率
     28  * 
     29  * */
     30 
     31 public class TestBuffer {
     32     
     33     @Test
     34     public void test3() {
     35         ByteBuffer buffer1 = ByteBuffer.allocateDirect(1024);
     36         System.out.println(buffer1.isDirect());
     37         ByteBuffer buffer2 = ByteBuffer.allocate(1024);
     38         System.out.println(buffer2.isDirect());
     39     }
     40     
     41     @Test
     42     public void test2() {
     43         String str = "abcd";
     44         ByteBuffer buffer = ByteBuffer.allocate(1024);
     45         
     46         buffer.put(str.getBytes());
     47         
     48         buffer.flip();
     49         
     50         byte[] bytes = new byte[buffer.limit()];
     51         buffer.get(bytes,0,2);
     52         
     53         //position = 2
     54         System.out.println(new String(bytes));
     55         System.out.println(buffer.position());
     56         
     57         //标记当前 position
     58         buffer.mark();
     59         
     60         //position = 4
     61         buffer.get(bytes,2,2);
     62         System.out.println(new String(bytes));
     63         System.out.println(buffer.position());
     64         
     65         //将 position reset 到 标记的位置  position = 2
     66         buffer.reset();
     67         System.out.println(buffer.position());
     68     }
     69     
     70     @Test
     71     public void test1() {
     72         //1.分配一个指定大小的缓冲区
     73         ByteBuffer buffer = ByteBuffer.allocate(1024);
     74         System.out.println("-------------allocate()-------------");
     75         System.out.println(buffer.position());
     76         System.out.println(buffer.limit());
     77         System.out.println(buffer.capacity());
     78         
     79         //2.利用 put() 存入数据到缓冲区
     80         String str = "abcedf";
     81         buffer.put(str.getBytes());
     82         System.out.println("-------------put()-------------");
     83         System.out.println(buffer.position());     //此时 位置 索引会变成6,即下一个要读取或写入的数据的索引 是 6 (byte[6])
     84         System.out.println(buffer.limit());
     85         System.out.println(buffer.capacity());
     86         
     87         //3.使用 get() 读取数据之前,需要调用 flip() 方法,切换到 读取数据模式 (将position置为0,limit置为原先position)
     88         //不然按照现在的所以 是无法读取到任何数据的
     89         buffer.flip();
     90         System.out.println("-------------flip()-------------");
     91         System.out.println(buffer.position());     
     92         System.out.println(buffer.limit());
     93         System.out.println(buffer.capacity());
     94                 
     95         //4.利用 get() 读取缓冲区中的数据
     96         //读取 需要创建一个容器去装
     97         byte[] bytes = new byte[buffer.limit()];
     98         //将读取到的数据 放到 这个 byte数组中
     99         buffer.get(bytes);
    100         
    101         System.out.println("-------------get()-------------");
    102         System.out.println(buffer.position());     
    103         System.out.println(buffer.limit());
    104         System.out.println(buffer.capacity());
    105         System.out.println(new String(bytes,0,bytes.length));
    106         
    107         //5.rewind() 可重复读  将位置设成 0 ,取消设置的 remark,现在就可以重新读取了
    108         buffer.rewind();
    109         System.out.println("-------------rewind()-------------");
    110         System.out.println(buffer.position());     
    111         System.out.println(buffer.limit());
    112         System.out.println(buffer.capacity());
    113         
    114         //6.clear()  清空缓存区,缓冲区中的数据依然存在,但是 处于 ‘被遗忘’状态
    115         buffer.clear();
    116         System.out.println("-------------clear()-------------");
    117         System.out.println(buffer.position());     
    118         System.out.println(buffer.limit());
    119         System.out.println(buffer.capacity());
    120         
    121         System.out.println((char)buffer.get());
    122     }
    123 }

  • 相关阅读:
    [zz]struct epoll_event
    [zz]libev 简介
    [zz]红黑树
    [zz]leveldb 实现原理
    [zz]使用 libevent 和 libev 提高网络应用性能
    [zz]AVL树
    [zz]do...while(0)的妙用
    Mybatis中的缓存简介
    Spring框架的介绍
    ThreadLocal
  • 原文地址:https://www.cnblogs.com/xuzekun/p/7435015.html
Copyright © 2011-2022 走看看