IO:即输入(Input)和输出(Output)
阻塞:当试图对该文件描述符进行读写时, 如果当时没有东西可读,或者暂时不可写, 程序就进入等待 状态, 直到有东西可读或者可写为止(强迫症,必须这件事做完才能做其他事情,否则一直等待)
非阻塞: 如果没有东西可读, 或者不可写, 读写函数马上返回, 而不会等待。(先取号,可以去做其他事情,叫号后,过来完成该事情)
同步:指的是用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪(亲力亲为且专注于一件事)
异步: 异步是指用户进程触发IO操作以后便开始做自己的事情,而当IO操作已经完成的时候会得到IO完成的通知(异步的特点就是通知,Java将IO读写委托给OS处理,需要将数据缓冲区地址和大小传给OS)即:指示别人帮自己做事,完成后得到通知
Bio、Nio和Aio三者比较
名称 | 说明 | 应用场景 | 补充 | 优点 | 缺点 |
Bio | 阻塞io | Apache,Tomcat。主要是并发量要求不高的场景. 服务器实现模式为一个连接一个线程 | 连接数目比较小且固定的架构 | 模型简单、 编码简单、 | 性能瓶颈低、不适合高并发 |
Nio | 同步非阻塞io | Nginx,Netty。主要是高并发量要求的场景. 服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。 | 连接数目多且 连接比较短(轻操作)的架构 | 性能瓶颈高 | 模型复杂、 编码复杂、 需处理半包问题 |
Aio | 异步非阻塞io | 还不是特别成熟,底层也基本是多线程模拟,所以应用场景不多,Netty曾经用了,但又放弃了。 服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。
| 连接数目多且连接比较长(重操作)的架构 |
|
|
假设有这么一个场景,有一排水壶(客户)在烧水。
AIO的做法是,每个水壶上装一个开关,当水开了以后会提醒对应的线程去处理。
NIO的做法是,叫一个线程不停的循环观察每一个水壶,根据每个水壶当前的状态去处理。
BIO的做法是,叫一个线程停留在一个水壶那,直到这个水壶烧开,才去处理下一个水壶。
可以看出AIO是最聪明省力,NIO相对省力,叫一个人就能看所有的壶,BIO最愚蠢,劳动力低下。
进程中的IO调用步骤:
- 进程向操作系统请求数据 ;
- 操作系统把外部数据加载到内核的缓冲区中;
- 操作系统把内核的缓冲区拷贝到进程的缓冲区 ;
- 进程获得数据完成自己的功能 ;
当操作系统在把外部数据放到进程缓冲区的这段时间(即上述的第二,三步),如果应用进程是挂起等待的,那么就是同步IO,反之,就是异步IO,也就是AIO 。
IO模型关系
Nio线程处理速度是否比BIO的快?
不是。改用nio只是让同时处理请求服务的数量增大,但是单个请求处理的时间是一样的。
使用Buffer提高IO效率的原因(这里与IO流里面的BufferedXXStream、BufferedReader、BufferedWriter提高性能的原理一样):IO的耗时主要花在数据传输的路上,普通的IO是一个字节一个字节地传输,
而采用了Buffer的话,通过Buffer封装的方法(比如一次读一行,则以行为单位传输而不是一个字节一次进行传输)就可以实现“一大块字节”的传输。比如:IO就是送快递,普通IO是一个快递跑一趟,采用了Buffer的IO就是一车跑一趟。很明显,buffer效率更高,花在传输路上
的时间大大缩短。
Nio与Aio的区别?
AIO是发出IO请求后,由操作系统自己去获取IO权限并进行IO操作;NIO则是发出IO请求后,由线程不断尝试获取IO权限,获取到后通知应用程序自己进行IO操作。
AIO只是帮助你从内核中将数据复制到用户空间中,并调用你传入的回调方法。
NIO 是需要程序自己从内核中将数据复制到用户空间中,并需要程序自己调用相应的处理逻辑。
Nio线程处理流程
其他补充:
1、系统并发量很大,容易出什么问题?
答:内存溢出,cpu处理不过来。
1.132位系统1个线程对象默认最大需要320kb内存,64位系统默认需要1M内存,业务对象还需要内存,容易造成内存不够。
1.2过多的线程需要os频繁切换,也大大影响性能。
1.3Java的new一个对象,调用操作系统的api,都存放在java的堆里。线程创建时有个栈空间,会消耗内存。
2、阻塞对线程池是否有影响?
阻塞等待接收客户端的数据时,这段时间占着线程,而线程池中线程数是有限的,并发量大是,将导致没有线程处理请求,请求的响应时间长,甚至拒绝服务。
3、请求的响应时间长,设置拒绝服务,这个问题是因为服务器的资源用到极致导致的吗?
不是。由于线程池的线程数不多,bio阻塞内一定有阻塞,处理能力存在上限。若不阻塞,并发量很大。
4、阻塞时,可以将线程让给别人吗?
不能让。只有在线程执行完,才能让出。
参考:1、https://juejin.im/entry/598da7d16fb9a03c42431ed3
2、https://www.cnblogs.com/doit8791/p/4951591.html
3、https://www.jianshu.com/p/901a6e35b3d9
4、https://www.cnblogs.com/ygj0930/p/6543960.html
5、https://juejin.im/entry/598da7d16fb9a03c42431ed3
6、https://blog.youkuaiyun.com/jijianshuai/article/details/77450746