### 5.1 零拷贝
零拷贝指的是数据不会重复拷贝到JVM内存当中,用户态和内核态之间没有拷贝操作,数据直接由内核缓冲区拷贝到另外的IO缓冲区(例如网卡的Socket缓冲区)。
以一般的Socket读写操作为例:将一个本地文件通过IO读出并写到网卡中。
~~~java
File f = new File("helloword/data.txt");
RandomAccessFile file = new RandomAccessFile(file, "r");
byte[] buf = new byte[(int)f.length()];
file.read(buf);
Socket socket = ...;
socket.getOutputStream().write(buf);
~~~
:-: ![](https://img.kancloud.cn/94/81/948100e00835ab21cb9aaf7ccf3f0604_492x263.png)
* Java本身并不具备IO读写的能力(所有的应用程序都是),对于IO读写的操作,要去调用操作系统提供的相关系统调用函数,通过系统调用会将进程从用户态切换到内核态(int 0x80)。
* 接着操作系统会通过DMA的方式进行IO的读写操作`拷贝(1)`,这个时候不用CPU参与,但是相对应的用户线程要被阻塞。
* 操作系统将数据从IO设备中读取出来之后存放到内核缓冲区中,接在再`拷贝(2)`到用户缓冲区中,这个过程从内核态转换到用户态。
* 用户缓冲区在处理数据之后调用writer方法将输入写入内核缓冲区(Socket缓冲区)(`拷贝(3)`),这个过程也要发生一次用户态到内核态的转换。
* 接着操作系统再使用DMA的方式将Socket缓冲区的内容写入到网卡中。(`拷贝4`)
可以发现:这个过程发生了3次用户态和内核态的切换,4次数据拷贝。
而在使用了直接内存之后就可以对数据的拷贝过程进行优化:
- 第一章 Java基础
- ThreadLocal
- Java异常体系
- Java集合框架
- List接口及其实现类
- Queue接口及其实现类
- Set接口及其实现类
- Map接口及其实现类
- JDK1.8新特性
- Lambda表达式
- 常用函数式接口
- stream流
- 面试
- 第二章 Java虚拟机
- 第一节、运行时数据区
- 第二节、垃圾回收
- 第三节、类加载机制
- 第四节、类文件与字节码指令
- 第五节、语法糖
- 第六节、运行期优化
- 面试常见问题
- 第三章 并发编程
- 第一节、Java中的线程
- 第二节、Java中的锁
- 第三节、线程池
- 第四节、并发工具类
- AQS
- 第四章 网络编程
- WebSocket协议
- Netty
- Netty入门
- Netty-自定义协议
- 面试题
- IO
- 网络IO模型
- 第五章 操作系统
- IO
- 文件系统的相关概念
- Java几种文件读写方式性能对比
- Socket
- 内存管理
- 进程、线程、协程
- IO模型的演化过程
- 第六章 计算机网络
- 第七章 消息队列
- RabbitMQ
- 第八章 开发框架
- Spring
- Spring事务
- Spring MVC
- Spring Boot
- Mybatis
- Mybatis-Plus
- Shiro
- 第九章 数据库
- Mysql
- Mysql中的索引
- Mysql中的锁
- 面试常见问题
- Mysql中的日志
- InnoDB存储引擎
- 事务
- Redis
- redis的数据类型
- redis数据结构
- Redis主从复制
- 哨兵模式
- 面试题
- Spring Boot整合Lettuce+Redisson实现布隆过滤器
- 集群
- Redis网络IO模型
- 第十章 设计模式
- 设计模式-七大原则
- 设计模式-单例模式
- 设计模式-备忘录模式
- 设计模式-原型模式
- 设计模式-责任链模式
- 设计模式-过滤模式
- 设计模式-观察者模式
- 设计模式-工厂方法模式
- 设计模式-抽象工厂模式
- 设计模式-代理模式
- 第十一章 后端开发常用工具、库
- Docker
- Docker安装Mysql
- 第十二章 中间件
- ZooKeeper