JAVA NIO vs IOhtml
当咱们学习了Java NIO和IO后,咱们很快就会思考一个问题:java
何时应该使用IO,何时我应该使用NIO缓存
在下文中我会尝试用例子阐述java NIO 和IO的区别,以及它们对你的设计会有什么影响服务器
Java NIO和IO的主要区别网络
IO | NIO |
面向Stream | 面向Buffer |
阻塞IO | 非阻塞IO |
Selectors |
面向Stream和面向Buffersocket
Java NIO和IO之间最大的区别是IO是面向流(Stream)的,NIO是面向块(buffer)的,因此,这意味着什么?工具
面向流意味着从流中一次能够读取一个或多个字节,拿到读取的这些作什么你说了算,这里没有任何缓存(这里指的是使用流没有任何缓存,接收或者发送的数据是缓存到操做系统中的,流就像一根水管从操做系统的缓存中读取数据)并且只能顺序从流中读取数据,若是须要跳过一些字节或者再读取已经读过的字节,你必须将从流中读取的数据先缓存起来。post
面向块的处理方式有些不一样,数据是先被 读/写到buffer中的,根据须要你能够控制读取什么位置的数据。这在处理的过程当中给用户多了一些灵活性,然而,你须要额外作的工做是检查你须要的数据是否已经所有到了buffer中,你还须要保证当有更多的数据进入buffer中时,buffer中未处理的数据不会被覆盖
学习
阻塞IO和非阻塞IOspa
全部的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工具对应用主要有如下几个方面的影响
一、使用IO和NIO的API是不一样的(废话)
二、处理数据的方式
三、处理数据所用到的线程数
处理数据的方式
在IO的设计里,要一个字节一个字节从InputStream 或者Reader中读取数据,想象你正在处理一个向下面的基于行分割的流
NIO的实现会有一些不一样,下面是一个简单的例子
想象一下,调用了read(buffer)方法后,只有半行数据被读进了buffer,例如:“Name: An”,你能如今就处理数据吗?固然不能。你须要等待直到至少一整行数据被读到buffer中,在这以前确保程序不要处理buffer中的数据
你如何知道buffer中是否有足够的数据能够被处理呢?你不知道,惟一的方法就是检查buffer中的数据。可能你会进行几回无效的检查(检查了几回数据都不够进行处理),这会令程序设计变得比较混乱复杂
is-data-in-buffer-ready 循环柱状图以下
总结
NIO容许你用一个单独的线程或几个线程管理不少个channels(网络的或者文件的),代价是程序的处理和处理IO相比更加复杂
若是你须要同时管理成千上万的链接,可是每一个链接只发送少许数据,例如一个聊天服务器,用NIO实现会更好一些,类似的,若是你须要保持不少个到其余电脑的链接,例如P2P网络,用一个单独的线程来管理全部出口链接是比较合适的
若是你只有少许的链接可是每一个链接都占有很高的带宽,同时发送不少数据,传统的IO会更适合
NIO图解