跳至主要內容
Java NIO - 零拷贝实现

Java NIO - 零拷贝实现

这里转一篇Java NIO 零拷贝的实现文章,在此之前建议先理解什么是Linux中零拷贝,可以先看这篇文章。本文从源码着手分析了 Java NIO 对零拷贝的实现,主要包括基于内存映射(mmap)方式的 MappedByteBuffer 以及基于 sendfile 方式的 FileChannel。最后在篇末简单的阐述了一下 Netty 中的零拷贝机制,以及 RocketMQ 和 Kafka 两种消息队列在零拷贝实现方式上的区别。

Java NIO零拷贝


gavin-james大约 17 分钟Java IO/NIO/AIOJava IO/NIO/AIO
Java N(A)IO - 框架: Netty

Java N(A)IO - 框架: Netty

Netty是一个高性能、异步事件驱动的NIO框架,提供了对TCP、UDP和文件传输的支持。作为当前最流行的NIO框架,Netty在互联网领域、大数据分布式计算领域、游戏行业、通信行业等获得了广泛的应用,一些业界著名的开源组件也基于Netty构建,比如RPC框架、zookeeper等。

NIO框架

目前流行的NIO框架非常的多。在论坛上、互联网上大家讨论和使用最多的有以下几种:

  • 原生JAVA NIO框架:

gavin-james大约 3 分钟Java IO/NIO/AIOJava IO/NIO/AIO
Java AIO - 异步IO详解

Java AIO - 异步IO详解

本文主要对异步IO和Java中对AIO的支持详解。

异步IO

上面两篇文章中,我们分别讲解了阻塞式同步IO、非阻塞式同步IO、多路复用IO 这三种IO模型,以及JAVA对于这三种IO模型的支持。重点说明了IO模型是由操作系统提供支持,且这三种IO模型都是同步IO,都是采用的“应用程序不询问我,我绝不会主动通知”的方式。

异步IO则是采用“订阅-通知”模式: 即应用程序向操作系统注册IO监听,然后继续做自己的事情。当操作系统发生IO事件,并且准备好数据后,在主动通知应用程序,触发相应的函数:


gavin-james大约 11 分钟Java IO/NIO/AIOJava IO/NIO/AIO
Java NIO - IO多路复用详解

Java NIO - IO多路复用详解

本文主要对IO多路复用,Ractor模型以及Java NIO对其的支持。

现实场景

我们试想一下这样的现实场景:

一个餐厅同时有100位客人到店,当然到店后第一件要做的事情就是点菜。但是问题来了,餐厅老板为了节约人力成本目前只有一位大堂服务员拿着唯一的一本菜单等待客人进行服务。

  • 那么最笨(但是最简单)的方法是(方法A),无论有多少客人等待点餐,服务员都把仅有的一份菜单递给其中一位客人,然后站在客人身旁等待这个客人完成点菜过程。在记录客人点菜内容后,把点菜记录交给后堂厨师。然后是第二位客人。。。。然后是第三位客人。很明显,只有脑袋被门夹过的老板,才会这样设置服务流程。因为随后的80位客人,再等待超时后就会离店(还会给差评)。
  • 于是还有一种办法(方法B),老板马上新雇佣99名服务员,同时印制99本新的菜单。每一名服务员手持一本菜单负责一位客人(关键不只在于服务员,还在于菜单。因为没有菜单客人也无法点菜)。在客人点完菜后,记录点菜内容交给后堂厨师(当然为了更高效,后堂厨师最好也有100名)。这样每一位客人享受的就是VIP服务咯,当然客人不会走,但是人力成本可是一个大头哦(亏死你)。
  • 另外一种办法(方法C),就是改进点菜的方式,当客人到店后,自己申请一本菜单。想好自己要点的才后,就呼叫服务员。服务员站在自己身边后记录客人的菜单内容。将菜单递给厨师的过程也要进行改进,并不是每一份菜单记录好以后,都要交给后堂厨师。服务员可以记录号多份菜单后,同时交给厨师就行了。那么这种方式,对于老板来说人力成本是最低的;对于客人来说,虽然不再享受VIP服务并且要进行一定的等待,但是这些都是可接受的;对于服务员来说,基本上她的时间都没有浪费,基本上被老板压杆了最后一滴油水。

gavin-james大约 31 分钟Java IO/NIO/AIOJava IO/NIO/AIO
Java NIO - 基础详解

Java NIO - 基础详解

新的输入/输出 (NIO) 库是在 JDK 1.4 中引入的,弥补了原来的 I/O 的不足,提供了高速的、面向块的 I/O。

Standard IO是对字节流的读写,在进行IO之前,首先创建一个流对象,流对象进行读写操作都是按字节 ,一个字节一个字节的来读或写。而NIO把IO抽象成块,类似磁盘的读写,每次IO操作的单位都是一个块,块被读入内存之后就是一个byte[],NIO一次可以读或写多个字节。

流与块

I/O 与 NIO 最重要的区别是数据打包和传输的方式,I/O 以流的方式处理数据,而 NIO 以块的方式处理数据。


gavin-james大约 8 分钟Java IO/NIO/AIOJava IO/NIO/AIO
Java IO - BIO 详解

Java IO - BIO 详解

BIO就是: blocking IO。最容易理解、最容易实现的IO工作方式,应用程序向操作系统请求网络IO操作,这时应用程序会一直等待;另一方面,操作系统收到请求后,也会等待,直到网络上有数据传到监听端口;操作系统在收集数据后,会把数据发送给应用程序;最后应用程序受到数据,并解除等待状态。

几个重要概念

  • 阻塞IO非阻塞IO

这两个概念是程序级别的。主要描述的是程序请求操作系统IO操作后,如果IO资源没有准备好,那么程序该如何处理的问题: 前者等待;后者继续执行(并且使用线程一直轮询,直到有IO资源准备好了)


gavin-james大约 10 分钟Java IO/NIO/AIOJava IO/NIO/AIO
IO 模型 - Unix IO 模型

IO 模型 - Unix IO 模型

本文主要简要介绍 Unix I/O 5种模型,并对5大模型比较,并重点为后续章节解释IO多路复用做铺垫。

Unix IO 模型简介

一个输入操作通常包括两个阶段:

  • 等待数据准备好
  • 从内核向进程复制数据

对于一个套接字上的输入操作,第一步通常涉及等待数据从网络中到达。当所等待分组到达时,它被复制到内核中的某个缓冲区。第二步就是把数据从内核缓冲区复制到应用进程缓冲区。


gavin-james大约 6 分钟Java IO/NIO/AIOJava IO/NIO/AIO
Java IO - 常见类使用

Java IO - 常见类使用

本文主要介绍Java IO常见类的使用,包括:磁盘操作,字节操作,字符操作,对象操作和网络操作。

IO常见类的使用

Java 的 I/O 大概可以分成以下几类:

  • 磁盘操作: File
  • 字节操作: InputStream 和 OutputStream
  • 字符操作: Reader 和 Writer
  • 对象操作: Serializable
  • 网络操作: Socket

gavin-james大约 3 分钟Java IO/NIO/AIOJava IO/NIO/AIO
Java IO - 源码: OutputStream

Java IO - 源码: OutputStream

本文主要从JDK 11源码角度分析 OutputStream。

OutputStream 类实现关系

OutputStream是输出字节流,具体的实现类层次结构如下:

img
img

gavin-james大约 6 分钟Java IO/NIO/AIOJava IO/NIO/AIO
Java IO - 源码: InputStream

Java IO - 源码: InputStream

本文主要从JDK 11 源码角度分析InputStream。

InputStream 类实现关系

InputStream是输入字节流,具体的实现类层次结构如下:

img
img

gavin-james大约 14 分钟Java IO/NIO/AIOJava IO/NIO/AIO