Java BIO、NIO和AIO。

Java NIO和IO的主要区别如下:

Java BIO、NIO和AIO。

面向流与面向缓冲

Java NIO和IO之间第一个最大的区别是,IO是面向流的,NIO是面向缓冲区的。 Java IO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。此外,它不能前后移动流中的数据。如果需要前后移动从流中读取的数据,需要先将它缓存到一个缓冲区。 Java NIO从缓冲区中读取数据,需要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。但是,还需要检查是否该缓冲区中包含所有您需要处理的数据。而且,需确保当更多的数据读入缓冲区时,不要覆盖缓冲区里尚未处理的数据。

阻塞与非阻塞IO

多路复用器(Selectors)

BIO:同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理。弊端:当客户端并发访问量增加后,服务端的线程个数和客户端并发访问数呈1:1的正比关系,Java中的线程也是比较宝贵的系统资源,线程数量快速膨胀后,系统的性能将急剧下降,随着访问量的继续增大,系统最终可能会崩溃。可以通过线程池机制改善,线程池可以实现线程复用,但如果发生大量并发请求,超过最大数量的线程就只能等待,直到线程池中的有空闲的线程可以被复用。如果你有少量的连接使用非常高的带宽,一次发送大量的数据,也许BIO服务器实现可能非常契合。

NIO:同步非阻塞,由Selector、Channel和buffer实现,采用reactor设计模型。Channel是一个双向的非阻塞通道,在通道的两边都可以进行数据的读写操作。Selector实现了用一个线程来管理多个通道,先把需要处理的Channel的IO事件(如connect、read、write)注册给Selector,selector里面的一个线程轮询多个通道,哪个通道里面有io读写事件发生,才会调用真正的io读写 函数进行操作。这里JDK使用了epoll()代替传统的select实现。(Linux多路复用,epoll的好处,相比于select、poll)。Buffer用来保存数据,可以用来存放从Channel读取的数据,也可以用来存放使用Channel进行发送的数据。有多种类型的buffer,bytebffer,charbuffer等。面向缓冲区比面向流更加高效。NIO在io操作的第二个阶段是阻塞的。在NIO的处理方式中,一个线程轮询多个socket,当某个socket里面真正有读写事件发生,交给后面的线程池去处理。线程池拿出一个线程线程进行处理,可能会等待后端应用的资源(JDBC连接等),其实这个线程就被阻塞了,当并发上来的话,还是会有BIO一样的问题。HTTP/1.1出现后,有了Http长连接,这个链接是一直打开的状态的,这样在NIO处理中可以进一步的进化,在后端资源中可以实现资源池或者队列,当请求来的话,线程池里面的线程把请求和请求数据传送给后端资源池或者队列里面就返回,并且在全局的地方保持住这个现场(哪个连接的哪个请求等),这样前面的线程还是可以去接受其他的请求,而后端的应用的处理只需要执行队列里面的就可以了,这样请求处理和后端应用是异步的.当后端处理完,到全局地方得到现场,产生响应,这个就实现了异步处理。而采用BIO在线程之间切换时需要上下文的切换。所以NIO效率较高。适用于连接数目多且连接比较短的架构,比如聊天服务器。




AIO:异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。适用于接数目多且连接比较长的架构。比如相册服务器,充分调用OS参与并发操作。

Java BIO、NIO和AIO。


相比于AIO,AIO用户线程只需要发送一个IO请求,其他什么都不用管,交给操作系统完成。需要操作系统底层的支持,jdk1.7支持。如果实在Linux系统下,AIO和NIO区别不大,因为AIO的底层也是基于epoll来实现的。但如果在Windows系统下,AIO底层性能较好,AIO比NIO有更高的吞吐量。还有一个leader-follower,好处是。。。。。。缺点是LF没有队列,处理请求数量和与线程池个数有关。NIO有队列解耦,NIO会把客户端的多个连接放到一个队列里面,然后负责轮询的线程从队列里面获取事件,进行轮询。