本文原创地址,
个人博客
:jsbintask.cn/2019/04/16/…(食用效果最佳),转载请注明出处!java
在理解什么是BIO,NIO,AIO以前,咱们首先须要了解什么是同步,异步,阻塞,非阻塞。假如咱们如今要去银行取钱: 同步
: 本身亲自出马持银行卡到银行取钱(使用同步IO时,Java本身处理IO读写); 异步
: 委托一小弟拿银行卡到银行取钱,而后给你(使用异步IO时,Java将IO读写委托给OS处理,须要将数据缓冲区地址和大小传给OS(银行卡和密码),OS须要支持异步IO操做API); 阻塞
: ATM排队取款,你只能等待(使用阻塞IO时,Java调用会一直阻塞到读写完成才返回); 非阻塞
: 柜台取款,取个号,而后坐在椅子上作其它事,等号广播会通知你办理,没到号你就不能去,你能够不断问大堂经理排到了没有,大堂经理若是说还没到你就不能去(使用非阻塞IO时,若是不能读写Java调用会立刻返回,当IO事件分发器会通知可读写时再继续进行读写,不断循环直到读写完成)编程
Blocking IO
,同步阻塞式IO,jdk1.4之前,一直采用BIO编程模型,在Socket
网络编程中,咱们一般会使用ServerSocket.accept()
方法获取一个新链接,该方法会阻塞当前主线程,因此一般一个链接来了后,会将其放入线程池去执行后续操做。而客户端发送请求后,先咨询服务端是否有线程相应,若是没有则会一直等待或者遭到拒绝请求,若是有的话,客户端Socket的connect方法一样会阻塞当前线程等待请求结束后才继续执行。后端
New IO
,同步非阻塞式IO,jdk1.4后引入,主要用于解决BIO大并发的问题,因为BIO会为任何链接都分配一个线程,而操做系统资源有限,若是客户端的请求过多,服务端程序可能会由于不堪重负而拒绝客户端的请求,甚至服务器可能会所以而瘫痪。服务器
NIO基于Reactor,当socket有流可读或可写入socket时,操做系统会相应的通知引用程序进行处理,应用再将流读取到缓冲区或写入操做系统。 也就是说,这个时候,已经不是一个链接就要对应一个处理线程了,而是有效的请求,对应一个线程,当链接没有数据时,是没有工做线程来处理的。 网络
Selector
在不断轮询注册这些新链接,当链接准备好后,再将其加入线程池。
HTTP/1.1出现后,有了Http长链接,这样除了超时和指明特定关闭的http header外,这个连接是一直打开的状态的,这样在NIO处理中能够进一步的进化,在后端资源中能够实现资源池或者队列,当请求来的话,开启的线程把请求和请求数据传送给后端资源池或者队列里面就返回,而且在全局的地方保持住这个现场(哪一个链接的哪一个请求等),这样前面的线程仍是能够去接受其余的请求,然后端的应用的处理只须要执行队列里面的就能够了,这样请求处理和后端应用是异步的.当后端处理完,到全局地方获得现场,产生响应,这个就实现了异步处理。并发
对应BIO中的ServerSocket
,Socket
,再NIO中的编程类为: ServerSocketChannel
, SocketChannel
,值得注意的是,它们的accept()
,connect
方法均不是阻塞的,当没有链接或者链接没有当即创建时,它们都会直接返回,不会阻塞当前线程!异步
值得注意的是,虽然jdk已经为咱们提供了NIO编程模型,可是使用难度较大,而且存在空轮询的bug。因此通常咱们会考虑使用在 jdk NIO的基础上继续封装的Netty
!socket
NIO.2
,异步非阻塞IO。jdk1.7引入。与NIO不一样,当进行读写操做时,只须直接调用API的read或write方法便可。这两种方法均为异步的,对于读操做而言,当有流可读取时,操做系统会将可读的流传入read方法的缓冲区,并通知应用程序;对于写操做而言,当操做系统将write方法传递的流写入完毕时,操做系统主动通知应用程序。 便可以理解为,read/write方法都是异步的,完成后会主动调用回调函数。 主要在java.nio.channels包下增长了下面四个异步通道: AsynchronousSocketChannel
, AsynchronousServerSocketChannel
, AsynchronousFileChannel
, AsynchronousDatagramChannel
其中的read/write方法,会返回一个带回调函数的对象,当执行完读取/写入操做后,直接调用回调函数。函数
关注我,这里只有干货!
操作系统