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

Java NIO学习篇(一)NIO的基本认识

程序员文章站 2022-04-24 10:50:59
...

定义:

NIO:是从jdk1.4提出的,本意是New IO(相对于传统的IO),也叫 No Blocked IO(只相对于网络IO),它的出现弥补传统IO的不足,提出了更加高效的方式。

NIO对于网络IO而言:

jdk1.4:采用了基于select/poll的多路复用IO模型。
jdk1.5及以上:采用了基于epoll的多路复用IO模型。

NIO对于文件IO而言:

NIO对基于文件的IO还是阻塞模型的IO。只有基于网络IO才是非阻塞的。

NIO的新特性:

  1. 基于通道(Channel)和缓冲区(Buffer)操作
  • 通道(Channel):一个新的、原始的IO抽象。
  • 缓冲区支持(Buffer):为所有的原始类型提供缓冲区支持。也就是说NIO是强制基于通道和缓冲区操作的。
  • 具体操作:数据从通道读到缓冲区,数据从缓冲区写入通道(用户进程角度)。
  1. 非阻塞(针对网络IO)
  • 提供多路复用、非阻塞的IO操作,即当前线程从通道读取数组到缓冲区时,或者把缓冲区数据写入到通道时,线程依然可以进行其他事情。
  1. 选择器(selectors)(针对网络IO)
  • 用户监听多个通道的事件,如:连接打开,数据到达等,单个线程可监听多个数据通道。
  1. 其他
  • 提供字符集编码、解码解决方案:java.nio.Charset。
  • 支持锁和内存映射文件的文件访问接口。

核心组件:

  • 通道(Channel):Java NIO的数据来源,可以是网络,也可以是本地磁盘。
  • 缓冲区(Buffer):数据读写的中转区。
  • 选择器(Selectors):异步IO的核心类,可以实现异步非阻塞IO,一个Selectors可以管理多个通道Channel。

一个复制文件的小demo:

/**
 * @author YeHaocong
 * @decription 一个NIO的Demo,完成对文件的复制
 * @Date 2020/5/18 18:52
 */

public class NIOFirstDemo {

    public static void main(String[] args) {

        try (FileInputStream fis = new FileInputStream("test_nio1.txt");
             FileOutputStream fos  = new FileOutputStream("test_nio1_cp.txt")){

            //获取输入流的通道。
            FileChannel fisChannel = fis.getChannel();
            //获取输出流的通道。
            FileChannel fosChannel = fos.getChannel();

            //创建缓冲区,并分配1024字节。

            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

            //把输入流的数据通过通道传输到ByteBuffer缓冲区中
            fisChannel.read(byteBuffer);

            //把缓冲区该为写模式。
            byteBuffer.flip();

            //把byteBuffer里面的数据通过输出流通道写到输出流中
            fosChannel.write(byteBuffer);

            //重置缓冲区
            byteBuffer.clear();
        }catch (IOException e){

        }
    }
}

运行流程图:
Java NIO学习篇(一)NIO的基本认识

  1. FileInputStream文件输入流从磁盘读取文件流。
  2. 把输入流读到通道Channel中。
  3. 把通道Channel中的数据读到ByteBuffer缓冲区。
  4. 把ByteBuffer缓冲区的数据写到通道中。
  5. 把通道中的数据写到文件输出流中。

IO和NIO的区别:

类型 面向操作域 处理数据 IO阻塞/非阻塞(基于网络IO)
Java IO 可以面向缓冲区,也可以直接面向数据源 没有缓冲区的话是直接读取字节或者字符,并且无法前后移动数据流中的数据 阻塞:当一个线程在读/写时,当数据完全被读取/写入或者数据没有准备好时,线程不能做其他任务,只能一直阻塞等待,知道数据准备好后才能继续。
Java NIO 强制面向缓冲区 先读取数据到缓冲区,并且可以前后移动数据量中的数据 非阻塞:当一个线程在读/写时,当数据完全被读取/写入或者数据没有准备好时,线程可以做其他任务(控制其他通道),知道数据准备好后再切换回该通道。继续读取、写入。