理解IO、NIO、 AIO

转载:https://baijiahao.baidu.com/s?id=1586112410163034993&wfr=spider&for=pc

niojava

同步: 本身亲自出马持银行卡到银行取钱(使用同步IO时,Java本身处理IO读写)。linux

异步: 委托一小弟拿银行卡到银行取钱,而后给你(使用异步IO时,Java将IO读写委托给OS处理,须要将数据缓冲区地址和大小传给OS(银行卡和密码),OS须要支持异步IO操做API)。nginx

阻塞: ATM排队取款,你只能等待(使用阻塞IO时,Java调用会一直阻塞到读写完成才返回)。web

非阻塞: 柜台取款,取个号,而后坐在椅子上作其它事,等号广播会通知你办理,没到号你就不能去,你能够不断问大堂经理排到了没有,大堂经理若是说还没到你就不能去 (使用非阻塞IO时,若是不能读写Java调用会立刻返回,当IO事件分发器会通知可读写时再继续进行读写,不断循环直到读写完成)。apache

1、IO NIO AIO编程

io、nio、aio的区别,相似于resin、apache、nginx在io处理上的区别,从多线程互不干扰的阻塞式执行(resin),到轮询式的同步非阻塞式(apache),再到异步非阻塞式(nginx)。windows

如今这三种io都在jdk中予以了支持。tomcat

IO (BIO)服务器

同步并阻塞,服务器实现模式为一个链接一个线程,每一个线程亲自处理io而且一直等待io的完成,即客户端有链接请求时服务器端就须要启动一个线程进行处理,若是这个链接不作任何事情会形成没必要要的线程开销,固然能够经过线程池机制改善。网络

IO的局限:IO是面向流的,阻塞式的,串行的一个过程。对每个客户端的socket链接,IO都须要一个线程来处理,并且在此期间,这个线程一直被占用,直到socket关闭。在这期间,tcp的链接、数据的读取、数据的返回都是被阻塞的。也就是说这期间大量的浪费了cpu的时间片和线程占用的内存资源。

每创建一个Socket链接时,同时建立一个新线程对该Socket进行单独通讯(采用阻塞的方式通讯)。这种方式具备很高的响应速度,而且控制起来也很简单,在链接数较少的时候很是有效,可是若是对每个链接都产生一个线程的无疑是对系统资源的一种浪费,若是链接数较多将会出现资源不足的状况。

NIO (new IO) 从jdk1.4开始

同步非阻塞,服务器实现模式为一个请求一个线程,每一个线程亲自处理io,但有另外的线程轮询检查是否io准备完毕,没必要等待io完成,即客户端发送的链接请求都会注册到多路复用器上,多路复用器轮询到链接有I/O请求时才启动一个线程进行处理。

**NIO则是面向缓冲区的,非阻塞式的,基于选择器的,用一个线程来轮询监控多个数据传输通道,哪一个通道准备好了(即有了一组能够处理的数据),就处理哪一个通道。 **

服务器端保存一个Socket链接列表,而后对这个列表进行轮询,若是发现某个Socket端口上有数据可读时(读就绪),则调用该socket链接的相应读操做;若是发现某个 Socket端口上有数据可写时(写就绪),则调用该socket链接的相应写操做;若是某个端口的Socket链接已经中断,则调用相应的析构方法关闭 该端口。这样能充分利用服务器资源,效率获得了很大提升。

AIO (Asynchronous io、NIO.2) 从jdk1.7开始

异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理,每一个线程没必要亲自处理io,而是委派os来处理,而且也不须要等待io完成了,若是完成后,os会通知的。

采用linux的epoll模型。

结论

在链接数很少的状况下,传统IO编写容易、方便使用。可是随着链接数的增多,问题传统IO就不行了。由于传统IO处理每一个链接都要消耗一个线程,而程序的效率当线程数很少时是随着线程数的增长而增长,可是到必定的数量以后,是随着线程数的增长而减小。因此传统阻塞式IO的 瓶颈在于不能处理过多的链接。

非阻塞式IO的出现的目的就是为了解决这个瓶颈。而非阻塞式IO是怎么实现的呢?非阻塞IO处理链接的线程数和链接数没有联系,也就是说处理10000个 链接非阻塞IO不须要10000个线程,你能够用1000个也能够用2000个线程来处理。由于非阻塞IO处理链接是异步的。当某个链接发送请求到服务 器,服务器把这个链接请求看成一个请求"事件",并把这个"事件"分配给相应的函数处理。咱们能够把这个处理函数放到线程中去执行,执行完就把线程归还。 这样一个线程就能够异步的处理多个事件。而阻塞式IO的线程的大部分时间都浪费在等待请求上了。

而后NIO的非阻塞,须要一直轮询,也是一个比较耗资源的,因此出现AIO 。

BIO、NIO、AIO适用场景

** BIO方式适用于链接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4之前的惟一选择,但程序直观简单易理解。**

**NIO方式适用于链接数目多且链接比较短(轻操做)的架构,好比聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。 **

AIO方式使用于链接数目多且链接比较长(重操做)的架构,好比相册服务器,充分调用OS参与并发操做,编程比较复杂,JDK7开始支持。

**ps:AIO、NIO是基于IO的,并非取代IO的意思。 **

2、NIO的框架

IO的概念:

就IO而言:概念上有5中模型:blocking I/O,nonblocking I/O,I/O multiplexing (select and poll),signal driven I/O (SIGIO),asynchronous I/O (the POSIX aio_functions)。

而后呢 不一样的操做系统对上述模型支持不一样: unix支持io多路复用,不一样系统叫法不一样 :freebsd里面叫 kqueue;linux 是epoll。而windows: 2000的时候就诞生了IOCP支持最后一种异步I/O

java是一种跨平台语言,为了支持异步IO,诞生了nio,Java1.4引入的NIO 1.0是基于I/O复用的。在各个平台上会选择不一样的复用方式。Linux用的epoll,BSD上用kqueue,Windows上应该是重叠I/O(确定不是IOCP)。

基于jdk的nio ,不一样公司出了一堆框架:apache mina ,jboss的netty,sun的grizzly。 这些都是直接封装传输层的tcp/udp。

nio直接使用比较难用,因此有了netty等针对网络io部分(tcp/udp-传输层)的封装(nio也有非网络io部分),为了使nio更易用。 ** netty等只是一个nio框架,不须要web容器的额外支持,也就是说不限定web容器。**

3个NIO框架是:

Mina

Mina(Multipurpose Infrastructure for Network Applications) 是 Apache组织一个较新的项目,它为开发高性能和高可用性的网络应用程序提供了很是便利的框架。当前发行的 Mina 版本2.04支持基于 JavaNIO 技术的 TCP/UDP 应用程序开发、串口通信程序,Mina 所支持的功能也在进一步的扩展中。目前,正在使用Mina的应用包括:Apache Directory Project、AsyncWeb、AMQP(Advanced MessageQueuing Protocol)、RED5 Server(Macromedia? FlashMedia RTMP)、ObjectRADIUS、 Openfire等等。

Netty

Netty是一款异步的事件驱动的网络应用框架和工具,用于快速开发可维护的高性能、高扩展性协议服务器和客户端。也就是说,Netty是一个NIO客户端/服务器框架,支持快速、简单地开发网络应用,如协议服务器和客户端。它极大简化了网络编程,如TCP和UDP套接字服务器。

Grizzly

Grizzly是一种应用程序框架,专门解决编写成千上万用户访问服务器时候产生的各类问题。使用JAVANIO做为基础,并隐藏其编程的复杂性。容易使用的高性能的API。带来非阻塞socketd到协议处理层。利用高性能的缓冲和缓冲管理使用高性能的线程池。

Servlet3.0 vs NIO

servlet3.0是一个规范、或者协议,能够用IO实现,也能够用NIO实现,而NIO则只是一种技术实现。一个是架构,一个是具体技术。

相同:

都提供了异步功能。

不一样:

jdk的nio直接使用比较难用,因此有了netty这些针对网络io部分(tcp/udp-传输层)的封装(nio也有非网络io部分),为了使nio更易用而已。

servlet3.0是另一个东西,不是对io的封装,而是javaee6众多规范中的一个。但凡javaee6的实现(或者像tomcat这种web容 器部分的实现),都会支持servlet3.0,servlet理论上能够支持多种应用层协议(不仅仅只是http),而servlet3.0之后提供的 异步特性与javase提供的nio或aio无直接关系,就是使用bio同样能够实现servlet3.0中提供的异步特性。

总结

到这里,深刻理解分布式系统协调技术介绍就结束了,,不足之处还望你们多多包涵!!以为收获的话能够点个关注收藏转发一波喔,谢谢大佬们支持。(吹一波,233~~)

相关文章
相关标签/搜索