程序员javaJava 杂谈

第十一节 netty前传-NIO 和IO对比

2018-11-01  本文已影响2人  勃列日涅夫

NIO和IO的区别

两者有两点最明显也是最主要的区别
IO:面向流、阻塞模式
NIO:面向缓冲、非阻塞模式

第一个重要区别是IO是面向流的,NIO是面向缓冲区的。

面向流的Java IO意味着可以从流中一次读取一个或多个字节。 至于用读取字节做什么取决于客户。 它们不会缓存在任何地方。 此外,你无法在流中的数据中前后移动。 如果需要在从流中读取的数据中前后移动,则需要先将其缓存在缓冲区中。

Java NIO的面向缓冲区的方法略有不同。 将数据读入缓冲区,稍后处理该缓冲区。 客户可以根据需要在缓冲区中前后移动。 这使得在处理过程中更具灵活性。 但是,还需要检查缓冲区是否包含完整处理所需的所有数据。 并且,需要确保在将更多数据读入缓冲区时,不要覆盖尚未处理的缓冲区中的数据。

第二个区别其实和和第一个也有很大关系。java io面向流,这就使得在从流中读写数据都是阻塞进行,而Java NIO一方面通过Selectors选择器允许单个线程监视多个输入通道。 也可以使用选择器注册多个通道,然后使用单个线程“select”已经准备好的通道。 这种选择器机制使单个线程可以轻松管理多个通道,另一方面面向缓冲使得java nio的读写可以立刻返回(非阻塞)。

相较而言java nio比java io更高效,但同时使用也更为复杂,比如下面例子

我的F:\book下有个a.txt内容如下

aaa
bbb
ccc

File file=new File("F:\\book\\a.text");
//获取输入流
InputStream input = new FileInputStream(file);
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
//逐行读取
String a = reader.readLine();
String b = reader.readLine();
String c = reader.readLine();
ByteBuffer buffer = ByteBuffer.allocate(48);
int bytesRead = inChannel.read(buffer);
ByteBuffer buffer = ByteBuffer.allocate(48);
 //注意:这个方法会记录读取的位置,所以后续读取不会从头开始读取
            int bytesRead = fileChannel.read(buffer);
            System.out.println(bytesRead);
            //读取到数据
            while(bytesRead != -1)
            {
                //反转后为可以读取缓冲中的数据
                buf.flip();
                while(buf.hasRemaining())//position < limit;表示可读
                {
                    //读取
                    System.out.print((char)buf.get());
                }
                //没有可读数据后,清除已读数据,从未读数据之后开始写入
                buf.compact();
                //开始继续读取
                bytesRead = fileChannel.read(buf);
            }

上面的代码也可简化入下图:


图片.png

也是由于nio的非阻塞和选择器这种特点,可以使得一个单线程管理多个通道,同时还可以让每一个通道使用单独的线程处理业务逻辑
简化如下:

图片.png

最后java并发包的设计者Doug Lea 有一篇关于nio的设计,我会在后续补上

上一篇 下一篇

猜你喜欢

热点阅读