• 十四、Java NIO 和 IO


    所有文章

    https://www.cnblogs.com/lay2017/p/12901123.html

    正文

    我们什么时候该使用IO,什么时候该使用NIO呢?

    本文会罗列一些NIO和IO的不同点,和用法,以及它们都是如何影响设计的。

    主要的不同点

    IO NIO
    面向流 面向缓冲区
    阻塞IO 非阻塞IO
    无选择器 有选择器

    面向流 VS 面向缓冲区

    面向流,意味着你将从一个流中有序地读取字节数据,你无法在流中前后移动操作位置。如果你想这么做,你必须把流全部读取出来,然后存储到一个buffer里面,继而前后移动操作位置。

    面向缓冲区就不同了,你可以在buffer上移动操作的位置。但是,面向缓冲区意味着你需要去判断哪些数据能够形成一套完整的信息。以及,你要确保新进入的数据不会覆盖了旧数据。

    阻塞 VS 非阻塞

    阻塞意味着当一个线程调用了read或者write,这个线程就不能做其它事情,必须等待io两阶段都结束。

    非阻塞就不同了,一个线程可以控制多个IO,当IO可用的时候线程再进行处理。线程可以做其它事情。

    选择器

    选择器是NIO独有的,选择器可以监控多个channel,使得单线程可以控制多个IO的输入输出。

    NIO和IO如何影响程序设计

    无论你选择哪种方式,将会影响以下三个方面

    1.调用NIO或者IO的API类

    2.数据的处理过程

    3.用于处理数据的线程数量

    API调用

    NIO和IO的API调用当然是不同的,这点毋庸置疑。

    数据处理

    在IO中,你将从流里面读取数据,例如你将逐行读取

    Name: Anna
    Age: 25
    Email: anna@mailserver.com
    Phone: 1234567890

    这个文本流在IO下可以这样处理

    InputStream input = ... ; // get the InputStream from the client socket
    
    BufferedReader reader = new BufferedReader(new InputStreamReader(input));
    
    String nameLine   = reader.readLine();
    String ageLine    = reader.readLine();
    String emailLine  = reader.readLine();
    String phoneLine  = reader.readLine();

    readLine方法返回的就会是一行数据,在此之前会阻塞等待,线程也不能做别的事,如图

     如果是NIO的实现

    ByteBuffer buffer = ByteBuffer.allocate(48);
    
    int bytesRead = inChannel.read(buffer);

    read方法会立即返回,bytesRead可能为0,也可能大于0。也就是说数据可能不会一次性读完,所以你需要循环调用

    ByteBuffer buffer = ByteBuffer.allocate(48);
    
    int bytesRead = inChannel.read(buffer);
    
    while(! bufferFull(bytesRead) ) {
        bytesRead = inChannel.read(buffer);
    }

    bufferFull方法校验是否构成了一个完整的数据信息,流程如图

     汇总

    NIO使得你可以单线程管理多个channel,但是也导致数据解析的复杂度上升。

    如果你需要并发很多连接,每个连接传输的数据量较小,例如聊天室程序,使用NIO是非常正确的。一个线程管理多个连接如图

     如果连接非常少,但是传输的数据非常大,那么采用传统IO比较合适,如图

  • 相关阅读:
    PHP 获取js中变量的方法
    Golang文件操作整理
    Golang的文件处理方式-常见的读写
    golang中文件以及文件夹路径相关操作
    服务器常用的状态码及其对应的含义
    left join on 和where条件的放置
    golang 文件导入数据追加sheet
    使用io/ioutil进行读写文件
    Go语言编程中字符串切割方法小结
    Golang学习
  • 原文地址:https://www.cnblogs.com/lay2017/p/12922012.html
Copyright © 2020-2023  润新知