Java——NIO

java中的输入输出都是以流的形式,包括文件读写和网络传输

传统的IO是面向流的,每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。而且需要为每个连接创建一个线程,当并发的连接数量非常巨大时,线程所占用的栈内存和CPU线程切换的开销将非常巨大。使用NIO,不再需要为每个线程创建单独的线程,可以用一个含有限数量线程的线程池,甚至一个线程来为任意数量的连接服务。由于线程数量小于连接数量,所以每个线程进行IO操作时就不能阻塞,如果阻塞的话,有些连接就得不到处理,NIO提供了这种非阻塞的能力。

NIO是面向缓冲区的,而且不会每个连接都占用一个线程,而且NIO是双向的。NIO主要由缓存、通道、选择器组成。

1、缓存(Buffer)

缓冲区在NIO中主要负责数据的存取,可以把它理解为需要被传输的数据的容器。缓冲区的底层是数组,用于存储不同类型的数据,根据数据类型的不同,分为七种相应类型的缓冲区。ByteBuffer、IntBuffer、LongBuffer、shortBuffer、CharBuffer、FloatBuffer、DoubleBuffer。

(1)缓冲区分别可以在直接内存和物理内存中通过相应方法获取:

  • 非直接缓冲区:通过allocate()方法分配缓冲区,将缓冲区建立在JVM的内存中;
  • 直接缓冲区:通过allocateDirect()方法分配直接缓冲区,将缓冲区建立在物理内存中,可以提供效率,缺点是内存占用比较大。

直接缓冲区和非直接缓冲区可以通过方法  buffer.isDirect()判断。

(2)缓冲区存取数据的两个核心方法分别是:

put():把数据存到缓冲区中

write():把缓冲区中的数据写出来

(3)缓冲区的四个核心属性:

private int mark = -1;        标记:表示记录当前position的位置,可以通过reset()恢复到mark标记的位置,如果reset是倒退,那么中间的数据将会被遗忘。

private int position = 0;     位置:表示缓冲区中正在操作的数据的位置。必须满足:position<=limit<=capacity

private int limit;            限制:表示缓冲区中的可以操作数据的大小,(limit后面的数据不能进行读写)

private int capacity;         容量:表示缓冲区中最大存储数据的容量,一旦声明,不能改变

缓冲区有读写两种模式,缓冲区被创建出来后默认是写模式,即只能往缓冲区里写入,如果需要读的话必须使用buffer.fli()方法切换,如果没有切换就去读,则会报错。

来创建一个简单的缓冲区,并通过方法获取它的属性的值: 

    ByteBuffer buffer=ByteBuffer.allocate(1024);
    System.out.println(" 当前指针位置"+ buffer.position());
    System.out.println(" 可操作数据长度"+ buffer.limit());
    System.out.println(" 总共数据长度"+  buffer.capacity());

结果如下所示:

那么此时缓冲区的结构就可以用下图表示:

 

然后我们再创建一个字符串,并将字符串写到缓冲区当中,然后再查看缓冲区的属性值。

          String str="abcde" ;
          buffer.put(str.getBytes());       //把字符串转换成byte数组形式存入缓存区
          System.out.println(" 当前指针位置"+ buffer.position());
          System.out.println(" 可操作数据长度"+ buffer.limit());
          System.out.println(" 总共数据长度"+  buffer.capacity());

结果如下图所示:

 可以看出指针位置发生了变化,而可操作数据长度和总数据长度没有变化,此时结构如下:

 然后将缓冲区切换到写模式:

        buffer.flip();              //切换到读取数据模式
        System.out.println(" 当前指针位置"+ buffer.position());
        System.out.println(" 可操作数据长度"+ buffer.limit());
        System.out.println(" 总共数据长度"+  buffer.capacity());

结果: 

可以看出来,因为空间中只有5个单位有数据,所以limit变为5,且指针位置为0,代表着只能对这5个数进行操作。

然后用get方法进行读取:

        byte[] dst=new byte[buffer.limit()];    //存有效数据长度即可
        buffer.get(dst);              //对buffer进行读取,并存储到bst数组中
        System.out.println(new String(dst));

打印出了最开始时候创建的字符串。 

2、通道(Channel)

3、选择器(Selector)
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值