JAVA中的IO模型主要涉及JVM与操作系统
具体原理如:对于一个IO读的操作,步骤如下:
1、数据先到操作系统的内核缓冲区
此时速度取决于网速与数据本身大小
2、络决于从内核缓冲区再到应用程序的地址空间
那么根据以上的原理,产生了几种IO模型
1、BIO
程序发送请求给内核,然后由内核去进行通信,在内核准备好数据之前这个线程是被挂起的,所以在两个阶段程序都处于挂起状态。
特点:BIO的特点就是在IO执行的两个阶段都被block了
2、NIO
与BIO的明显区别是,发起第一次请求后,线程并没有被阻塞,它反复检查数据是否准备好,把原来大块不能用的阻塞时间分成了许多“小阻塞”(检查),所以进程不断有机会被执行。这个检查有没有准备好数据的过程有点类似于“轮询”。
NIO的特点就是程序需要不断的主动询问内核数据是否准备好。第一个阶段非阻塞,第二个阶段阻塞
后绪在JAVA1.4出来以后,实际上就是IO多路复用了,具体见下面
3、IO多路复用
我们思考NIO模式,如果把NIO中的查询这个事交给别人的线程做,是不是省事。可以交给select来做这个事。
类似的模式还有poll,epoll方式。
- select: 注册事件由数组管理, 数组是有长度的, 32位机上限1024, 64位机上限2048。轮询查找时需要遍历数组。
- poll:把select的数组采用链表实现,因此没了最大数量的限制
- epoll方式:基于事件回调机制,回调时直接通知进程,无须使用某种方式来查看状态。
JAVA1.4以后NIO的思路就是IO多路复用的思路
特点:用户进程能同时等待多个IO请求,系统来监控IO状态,其中的任意一个进入读就绪状态,select函数就可以返回。
所以能处理多个IO请求是他的优势,若连接不是很多的话,它的效率不一定高,可能还会更差。
为什么可以这么操作就是因为select机制,因为select不是等到所有数据准备好才返回,而是只要有一个准备好就返回,
具体怎么操作呢?JAVA在套接字上提供selector选择机制,当发起select()时会阻塞等待至少一个事件返回。
4\ AIO Asynchronous I/O(异步 I/O),这是Java 1.7引入的NIO 2.0中用到的
可以看到这是一个异步的过程
JAVA针对这种模型提供了一种处理返回结果的技巧:
- 一种是基于”回调”,我们可以实现CompletionHandler接口,在调用时把回调函数传递给对应的API即可
- 另一种是返回一个Future。处理完别的事情,可以通过isDone()可查看是否已经准备好数据,通过get()方法等待返回数据。
总结一个:BIO,NIO,IO多路在整个过程中,或全部等待返回,或是部分等待返回,所以都属于同步形态
AIO全程都不需要等待,才是异步的。