同步:调用者要一直等待调用结果的通知后才能进行后续的执行
异步:指被调用方先返回应答让调用者先回去,然后再计算调用结果,计算完最终结果后再通知并返回给调用方
理解:同步、异步的讨论对象是被调用者(服务提供者),重点在于获得调用结果的消息通知方式上
阻塞:调用方一直在等待而且别的事情什么都不做,当前线/进程都会被挂起,线程暂停
非阻塞:调用在发出去后,调用方先去忙别的事情,不会阻塞当前进/线程,而会立即返回
理解:阻塞、非阻塞的讨论对象是调用者(服务请求者),调用者是否能干其他事
同步阻塞、同步非阻塞、同步多路复用、异步阻塞(没有此情况)、异步非阻塞
当调用一次 channel.read 或 stream.read 后,会切换至操作系统内核态来完成真正数据读取,而读取又分为两个阶段,分别为:
等待数据阶段
复制数据阶段
1. 阻塞 IO
用户线程被阻塞
2. 非阻塞 IO
用户线程没有被阻塞 ,等待数据,一直循环去调用,复制数据,用户线程也是被阻塞
3. 多路复用
调用select方法,把多个channel发生的事件一次返回,
4. 异步 IO
阻塞IO:在做一件事情的 时候,做不了其他事情
多路服用:调用select方法,把多个channel发生的事件一次返回,
BIO:同步阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理。
NIO:同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。
要想理解零拷贝,就要了解操作系统IO流程
java 本身并不具备 IO 读写能力,因此 read 方法调用后,要从 java 程序的用户态切换至内核态,这期间用户线程阻塞,操作系统使用 DMA将磁盘中的数据拷贝到内核缓冲区中
从内核态切换回用户态,将数据从内核缓冲区读入用户缓冲区(即 byte[] buf),这期间 cpu 会参与拷贝
服务器对请求进行响应的时候,会调用 write 方法,这时将数据从用户缓冲区(byte[] buf)写入 socket 缓冲区,cpu 会参与拷贝
网络适配器通过 DMA 将 socket 缓冲区的数据copy到网卡中,最后由网卡把数据发送出去
在这个过程中用户态与内核态的切换发生了 3 次,这个操作比较重量级,数据拷贝了共 4 次,所谓的零拷贝,就是通过各种方式,减少数据拷贝的次数