您的位置:首页 > 大数据 > 人工智能

BIO、NIO、AIO

2016-01-26 11:50 316 查看
     java到现在jdk1.8,已经经历了三代io,第一代也就是从jdk1.1到1.4使用的是BIO,BIO是select的,也就是同步阻塞的IO方式,到jdk1.4-1.7jdk采用全新的NIO,newIO是poll的,NIO是同步非阻塞的,而到了jdk1.7-1.8出现了AIO,而AIO使用的是epoll方式,该方式最大亮点就是异步非阻塞。

同步和异步
     同步异步说的是消息调用的机制,同步就是当前调用者发出调用,调用者一直等待,在没有得到结果之前是不会返回的,而异步就是当前调用者发出调用,调用者不需要等待返回,而是在调用发出后被调用者返回一个状态或通知或者回调来处理。
     举个栗子:我去书店买书,然而老板告诉我书卖没了,过一天再过来看,过了一天我又去书店问,如此一直等到买到书,这就是同步,而异步是我去书店买书,老板告诉我书卖没了,说到有书的时候打电话通知我过来取。。。。。。。。。,这就是异步。
阻塞和非阻塞
     阻塞和非阻塞说的是程序等待调用结果时的状态。阻塞就是调用者在发起调用的时候,当前线程被挂起,只有等待调用完成返回结果才停止阻塞,而非阻塞则是在发起调用时你可以去做其他事,当调用完成时返回一个回调就行了。

BIO
     传统的BIO也就是Blocking IO,它是同步阻塞方式进行IO传输的。在进行网络连接时,首先我们需要client端和server端连接,server端需要accept,一旦建立连接,client就可以和server进行通信,包括 write、read,BIO是通过轮询的方式请求数据也就是同步请求,当client和server建立连接后其他线程是被阻塞的。BIO性能是很捉急的,包括两个方面,1.阻塞,2.以linux为例,select方式请求文件系统fd(linux中所有资源都是用file
directory定义的)是有限的。每次读写请求都会将可用的fd资源拷贝一遍,并且在内存中遍历fd。请看下面的图:



     在操作系统中,都分为kernel区和用户区,当请求数据时,是需要从内核进程将数据拷贝到用户区的buffer中,只要数据没有请求完,当前线程一直被阻塞,同时,当有多个线程请求数据,处理线程阻塞和阻塞恢复需要涉及kernel区和用户区context切换,这是非常消耗性能的,可以想象如果有大量的线程请求数据时的效率。并且,BIO在系统底层使用select方式,在select中使用一个bitMap装fd参数,bitMap是有大小限制的,32*32
int,也就是1024,当请求超过1024个fd时是没有办法的。

NIO
     NIO使用的是非阻塞的方式,说是非阻塞的方式其实还是有阻塞的,只是阻塞的粒度更细了,在NIO中是使用忙循环的形式,同时NIO使用了多路复用IO,多路复用IO是单进程多线程的方式,也就是说一个selector可以使用多个channel,之前也说到NIO使用的是忙循环形式并不是阻塞的,一开始有一个select方法用来查找可用的channel,这里是阻塞的,必须先取到可有线程,但是这个粒度更细,只在某一步阻塞,并不是整个线程阻塞,当没有满足条件就一直忙循环,等其他线程操作。并且NIO的请求fd的数量是无限的,只要你内存撑得住,因为内部不再使用bitMap而是链表。
AIO(
Asynchronous IO)
     AIO是异步非阻塞,异步IO既提供文件系统的API,也提供sockets异步通道接口。AIO异步通道接口提供两套方法来监控和控制异步操作(connect,read,write),第一种使用future,通过返回future对象,来检查futrue的状态发现调用时完成还是失败,还是正在进行;第二种提供一个回调参数completionHandler,该回调方法提供complete方法和fail方法。异步IO底层调用在linux里面是使用epoll,在windows下是iocp,对iocp不熟悉,epoll技术核心也不是很了解,只清楚一点就是,不再像select方式和poll方式,需要通过kernel区将数据拷贝到用户区,我能不能直接不通过kernel,直接写到用户的buffer中呢?其实是可以的,当前有DMA技术。
     那么AIO这么牛逼是不是NIO和BIO都不用了我只需要用AIO呢,其实不是的,要看使用场景,大部分时间NIO很好用,它适用于并发量高的短连接比如即时聊天,而AIO则适合长连接操作,比如视频聊天。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  nio io aio