java中的I/O模型

来源:互联网 发布:飞行时间质谱仪数据 编辑:程序博客网 时间:2024/05/22 10:49

1.linux下的I/O模型
在了解java中的I/O模型之前先了解下linux下的I/O模型
linux的内核将所有的外部设备都看成一个文件来操作,对于一个文件的读写操作会调用内核提供的系统命令,返回一个file description。而对于一个socket的读写也会有相应的描述符,称为socketfd,它指向内核中的一个结构体
1.1阻塞I/O模型:进程调用f这个函数,f函数直到数据包到达应用进程的缓冲区或者发生错误才返回,期间应用进程会一直被阻塞。
1.2.非阻塞I/O模型:进程调用f这个函数,f函数检查缓冲区有没有数据,没数据直接返回,进程可以不会被阻塞。这个检查过程会轮询进行。
1.3 I/O复用模型:linux提供一个select/epoll,进程把多个fd传到select上,由select来完成1.2中的动作
1.4:信号驱动模型:系统调用信号处理函数,当数据就绪时,通知应用程序来调用f函数来读取数据
1.5:异步模型:告知内核启动某个操作,并在内核在整个操作完成后通知我们。
五个模型理解起来还是有点困难,自己对后三种模型的理解也不是很透彻。
2.java中的通信模型
2.1BIO模型:一个独立的accepter负责监听客户端的连入,一旦有一个客户端连入,服务器端就启动一个线程与之链接。一个客户端对应服务器端的一个线程。
这里写图片描述
缺点1.如果没有客户端接入。主线程会阻塞在监听客户端操作上
2.如果客户端过多,服务器的线程就会很多,无法满足高并发高性能要求。
2.2伪异步模型:将客户端的封装成一个task丢到线程池中,服务端通过线程池与客户端建立连接.
这里写图片描述
特点:1.由于线程池的数量可以控制,所以不会出现2.1中因为客户端过多而导致服务器资源耗尽的风险。
2.但是其底层也是基础阻塞模型的,所以也是阻塞的。用户请求过多时,会被阻塞在线程池中的同步队列中
2.3NIO模型:服务器端将Channel注册在selector上,服务器端的主线程会不断去看selector上的Channel是否有事件产生。如果没有则会去干别事。
2.4AIO模型:引入了异步通道的概念,不需要selector,2.3中检查的任务由内核完成,并通知主线程。
用一个形象的例子来类比:
2.1:烧开水,你一直待在水壶边上看它有没有开,期间不能干别的事情。
2.3:烧开水,你让它烧在那,期间可以去洗脸,但是是不是要回来看看水开了没。
2.4:烧开水,你让它在那烧,期间可以去洗脸刷牙,水开了火自动会熄灭并且发出响声,你可以去接开水了。
几种模型的对比
bio 伪异步 nio aio
客户端个数:i/o线程 1:! m:n m:1 m:0
api难度 简单 简单 非常复杂 复杂
调试难度 简单 简单 非常复杂 复杂
性能 非茶差 差 高 高
吞吐量 低 中 高 高