面试时答:

IO是面向流的,NIO是面向缓冲区的
Java IO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方;
NIO则能前后移动流中的数据,因为是面向缓冲区的
IO流是阻塞的,NIO流是不阻塞的
Java IO的各种流是阻塞的。这意味着,当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了
Java NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。NIO可让您只使用一个(或几个)单线程管理多个通道(网络连接或文件),但付出的代价是解析数据可能会比从一个阻塞流中读取数据更复杂。
非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。
选择器
Java NIO的选择器允许一个单独的线程来监视多个输入通道,你可以注册多个通道使用一个选择器,然后使用一个单独的线程来“选择”通道:这些通道里已经有可以处理的输入,或者选择已准备写入的通道。这种选择机制,使得一个单独的线程很容易来管理多个通道。
NIO的优势:
1.优势在于一个线程管理多个通道;但是数据的处理将会变得复杂;
2.如果需要管理同时打开的成千上万个连接,这些连接每次只是发送少量的数据,采用这种;
传统IO的优势:
1.适用于一个线程管理一个通道的情况;因为其中的流数据的读取是阻塞的;
2.如果需要管理同时打开不太多的连接,这些连接会发送大量的数据;

现代的酒店服务方式跟传统的区别有两个:
1、增加了一个角色,要有一个专门负责收集客人需求的人。NIO里对应的就是Selector。
2、由阻塞服务方式改为非阻塞服务了,客人吃着的时候服务员不用一直侯在客人旁边了。传统的IO操作,比如read(),当没有数据可读的时候,线程一直阻塞被占用,直到数据到来。NIO中没有数据可读时,read()会立即返回0,线程不会阻塞。
NIO中,客户端创建一个连接后,先要将连接注册到Selector,相当于客人进入餐厅后,告诉前台你要用餐,前台会告诉你你的桌号是几号,然后你就可能到那张桌子坐下了,SelectionKey就是桌号。当某一桌需要服务时,前台就记录哪一桌需要什么服务,比如1号桌要点菜,2号桌要结帐,服务员从前台取一条记录,根据记录提供服务,完了再来取下一条。这样服务的时间就被最有效的利用起来了。

区别:

IO NIO
面向Stream 面向Buffer
阻塞IO 非阻塞IO
  Selectors

Java NIO提供了与标准IO不同的IO工作方式: 
Channels and Buffers(通道和缓冲区):标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。
Asynchronous IO(异步IO):Java NIO可以让你异步的使用IO,例如:当线程从通道读取数据到缓冲区时,线程还是可以进行其他事情。当数据被写入到缓冲区时,线程可以继续处理它。从缓冲区写入通道也类似。
Selectors(选择器):Java NIO引入了选择器的概念,选择器用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个的线程可以监听多个数据通道。

面向Stream和面向Buffer

Java NIO和IO之间最大的区别是IO是面向流(Stream)的,NIO是面向块(buffer)的,所以,这意味着什么?

面向流意味着从流中一次可以读取一个或多个字节,拿到读取的这些做什么你说了算,这里没有任何缓存(这里指的是使用流没有任何缓存,接收或者发送的数据是缓存到操作系统中的,流就像一根水管从操作系统的缓存中读取数据)而且只能顺序从流中读取数据,如果需要跳过一些字节或者再读取已经读过的字节,你必须将从流中读取的数据先缓存起来。

面向块的处理方式有些不同,数据是先被 读/写到buffer中的,根据需要你可以控制读取什么位置的数据。这在处理的过程中给用户多了一些灵活性,然而,你需要额外做的工作是检查你需要的数据是否已经全部到了buffer中,你还需要保证当有更多的数据进入buffer中时,buffer中未处理的数据不会被覆盖

阻塞IO和非阻塞IO

所有的Java IO流都是阻塞的,这意味着,当一条线程执行read()或者write()方法时,这条线程会一直阻塞知道读取到了一些数据或者要写出去的数据已经全部写出,在这期间这条线程不能做任何其他的事情

java NIO的非阻塞模式(Java NIO有阻塞模式和非阻塞模式,阻塞模式的NIO除了使用Buffer存储数据外和IO基本没有区别)允许一条线程从channel中读取数据,通过返回值来判断buffer中是否有数据,如果没有数据,NIO不会阻塞,因为不阻塞这条线程就可以去做其他的事情,过一段时间再回来判断一下有没有数据

NIO的写也是一样的,一条线程将buffer中的数据写入channel,它不会等待数据全部写完才会返回,而是调用完write()方法就会继续向下执行

Selectors

Java NIO的selectors允许一条线程去监控多个channels的输入,你可以向一个selector上注册多个channel,然后调用selector的select()方法判断是否有新的连接进来或者已经在selector上注册时channel是否有数据进入。selector的机制让一个线程管理多个channel变得简单。

NIO和IO对应用的设计有何影响

选择使用NIO还是IO做你的IO工具对应用主要有以下几个方面的影响

1、使用IO和NIO的API是不同的(废话)

2、处理数据的方式

3、处理数据所用到的线程数

处理数据的方式

在IO的设计里,要一个字节一个字节从InputStream 或者Reader中读取数据,想象你正在处理一个向下面的基于行分割的流

Name:Anna
Age: 25
Email: 50330690@qq.com
Phone:1234567890

处理文本行的流的代码应该向下面这样

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();

注意,一旦reader.readLine()方法返回,你就可以确定整行已经被读取,readLine()阻塞知道一整行都被读取

NIO的实现会有一些不同,下面是一个简单的例子

ByteBuffer buffer = ByteBuffer.allocate(48);

int bytesRead = inChannel.read(buffer);

注意第二行从channel中读取数据到ByteBuffer,当这个方法返回你不知道是否你需要的所有数据都被读到buffer了,你所知道的一切就是有一些数据被读到了buffer中,但是你并不知道具体有多少数据,这使程序的处理变得稍微有些困难

想象一下,调用了read(buffer)方法后,只有半行数据被读进了buffer,例如:“Name: An”,你能现在就处理数据吗?当然不能。你需要等待直到至少一整行数据被读到buffer中,在这之前确保程序不要处理buffer中的数据

你如何知道buffer中是否有足够的数据可以被处理呢?你不知道,唯一的方法就是检查buffer中的数据。可能你会进行几次无效的检查(检查了几次数据都不够进行处理),这会令程序设计变得比较混乱复杂

ByteBuffer buffer = ByteBuffer.allocate(48);

int bytesRead = inChannel.read(buffer);

while(! bufferFull(bytesRead) ) {
bytesRead = inChannel.read(buffer);
}

bufferFull方法负责检查有多少数据被读到了buffer中,根据返回值是true还是false来判断数据是否够进行处理。bufferFull方法扫描buffer但不能改变buffer的内部状态

is-data-in-buffer-ready 循环柱状图如下

总结

NIO允许你用一个单独的线程或几个线程管理很多个channels(网络的或者文件的),代价是程序的处理和处理IO相比更加复杂

如果你需要同时管理成千上万的连接,但是每个连接只发送少量数据,例如一个聊天服务器,用NIO实现会更好一些,相似的,如果你需要保持很多个到其他电脑的连接,例如P2P网络,用一个单独的线程来管理所有出口连接是比较合适的

如果你只有少量的连接但是每个连接都占有很高的带宽,同时发送很多数据,传统的IO会更适合

 

面试题思考:IO 和 NIO的区别,NIO优点的更多相关文章

  1. Java NIO:IO与NIO的区别 -阿里面试题

    一.概念 NIO即New IO,这个库是在JDK1.4中才引入的.NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多.在Java API中提供了两套N ...

  2. java中的NIO和IO到底是什么区别?20个问题告诉你答案

    摘要:NIO即New IO,这个库是在JDK1.4中才引入的.NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多. 本文分享自华为云社区<jav ...

  3. netty1---传统IO和NIO的区别

    传统IO: package OIO; import java.io.IOException; import java.io.InputStream; import java.net.ServerSoc ...

  4. Java IO学习笔记六:NIO到多路复用

    作者:Grey 原文地址:Java IO学习笔记六:NIO到多路复用 虽然NIO性能上比BIO要好,参考:Java IO学习笔记五:BIO到NIO 但是NIO也有问题,NIO服务端的示例代码中往往会包 ...

  5. Java IO模型:BIO、NIO、AIO

    Java IO模型:BIO.NIO.AIO 本来是打算直接学习网络框架Netty的,但是先补充了一下自己对Java 几种IO模型的学习和理解.分别是 BIO.NIO.AIO三种IO模型. IO模型的基 ...

  6. Java IO、网络编程、NIO、Netty、Hessian、RPC、RMI的学习路线

    好久没看Java IO这块的内容,感觉都快忘得差不多了.平成编程也没有设计到太多的Java基础知识,所以这里希望可以抽点时间回顾一下,让艾宾浩斯记忆曲线不要下降的太快. 回顾这个主要还是以总结为主,能 ...

  7. Java 网络IO编程(BIO、NIO、AIO)

    本概念 BIO编程 传统的BIO编程 代码示例: public class Server { final static int PROT = 8765; public static void main ...

  8. Java--Stream,NIO ByteBuffer,NIO MappedByteBuffer性能对比

    目前Java中最IO有多种文件读取的方法,本文章对比Stream,NIO ByteBuffer,NIO MappedByteBuffer的性能,让我们知道到底怎么能写出性能高的文件读取代码. pack ...

  9. 【Java nio】java nio笔记

    缓冲区操作:缓冲区,以及缓冲区如何工作,是所有I/O的基础.所谓“输入/输出”讲的无非就是把数据移出货移进缓冲区.进程执行I/O操作,归纳起来也就是向操作系统发出请求,让它要么把缓冲区里的数据排干,要 ...

  10. Java-杂项-java.nio:java.nio

    ylbtech-Java-杂项-java.nio:java.nio java.nio全称java non-blocking IO,是指jdk1.4 及以上版本里提供的新api(New IO) ,为所有 ...

随机推荐

  1. logback 配置解析

    http://www.cnblogs.com/cb0327/p/5759441.html 正文 回到顶部 1.根节点<configuration>包含的属性 scan: 当此属性设置为tr ...

  2. Nutch的发展历程(转)

    2002年8月由Doug Cutting发起,托管于Sourceforge,之后发布了0.4.0.5.0.6三个版本 2004年9月Oregon State University(俄勒冈州立大学)采用 ...

  3. android studio教学视频资源(点开即看)

    android studio教学视频资源(点开即看) 自从Google推出android studio之后.包含github在内的非常多第三方代码库项目很多其它的採用的android studio编译 ...

  4. sklearn中xgboost模块中plot_importance函数(特征重要性)

    # -*- coding: utf-8 -*- """ ######################################################### ...

  5. 【JS设计模式】装饰者模式

    装饰者模式:在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能.它是通过创建一个包装对象,也就是装饰来包裹真实的对象 装饰模式的特点 (1) 装饰对象和真实对象有同样的接口.这样clien ...

  6. CCNA2.0笔记_ACL

    要点: 1.按顺序执行,一旦某条语句匹配,后续语句不再处理. 2.默认ACL 结尾语句是deny any,所以你要记住的是在ACL 里至少要有1 条permit 语句. 3.记得创建了ACL 后要把它 ...

  7. HTML5之语音识别实例

    HTML5之语音识别实例 代码 <input type="text"  x-webkit-speech id="d1" lang="zh-CN& ...

  8. JVM Specification 9th Edition (4) Chapter 4. The class File Format

    Chapter 4. The class File Format Table of Contents 4.1. The ClassFile Structure 4.2. Names 4.2.1. Bi ...

  9. (转)64位开源处理器Rocket的源代码简单介绍

    转载地址: http://blog.csdn.net/leishangwen/article/details/46604819 最近大概阅读了一下UCB发布的Rocket处理器的源码,对源代码各个文件 ...

  10. 大数据处理-Trie树

    大数据处理--Trie树 1.1.什么是Trie树 Trie树,即字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被 ...