小伙伴们在工作中是否经常听到系统瓶颈这个词,系统的瓶颈一般取决于系统属于IO密集型和CPU密集型,Java web项目中,一般系统的瓶颈都取决于IO而非CPU,CPU不是也不应该是Java项目的瓶颈所在;所以说,IO是比较重要的知识点,了解IO的原理和模型,对于我们开发大型项目是有必要的。
IO的基本原理
IO涉及到的主要有read和write两大系统调用,以write为例,一次write调用并非是直接将用户进程的数据直接传输到网卡等输出设备,而是操作系统将数据从用户进程的缓冲区复制到内核缓冲区,然后操作系统再将数据通过网卡等设备进行输出,read调用也同理。
所以说IO的过程主要分为两阶段,并且读写是相反的,read是先输入再复制,write是先复制再输出。
模型
- 同步阻塞IO(Blocking IO)
- 特点:两阶段都阻塞
- 优点:简单,易于理解
- 缺点:在多线程的场景下使用,一个线程对应一个连接,大量的线程频繁地切换将会降低系统的效率
- 同步非阻塞NIO (None-Blocking IO)
- 特点:在数据输入的时候不阻塞,在复制数据的时候阻塞,需要轮询直至数据就绪
- 优点:相较于同步阻塞IO更加灵活,数据未就绪也可以做其他事情
- 缺点:轮询需要占用大量的CPU时间,从而导致系统效率低下
- IO多路复用(IO Multiplexing)
- 特点: 采用了React反应器模式,Java的Selector和linux的epoll都是采用了这种模型。将连接注册到select,使用一个select查询线程来轮询内核,返回一个就绪的连接的列表,然后再进行复制,select调用和复制数据都是阻塞的。
- 优点:一个线程便可以管理成千上万个连接,十分高效
- 缺点:本质上是使用的阻塞的IO,阻塞便会使系统吞吐量降低
- 异步IO
- 向内核注册IO操作并调用,然后用户进程或线程就可以去处理其他事情,当数据就绪后,操作系统将数据复制到缓存区,然后向调用的进程发送信号或者执行注册的回调函数。
- 优点:全程无阻塞,真正的异步
- 缺点:需要操作系统内核的支持
写在最后
笔者是一名初出茅庐的码农,在此记录学习中的收获,如有错误,欢迎各位大佬进行批评指正