IO,就是Input和Output。是对信息、也就是数据,也就是二进制的输入输出。
根据数据的来源,或者操作方式,就有不同的分类。
按读取来源分,则有:
1、对文件的输入输出,硬件层面读取的是硬盘。
2、网络的输入输出,硬件层面读取的网卡。
按同异步是否阻塞分,则有:
1、同步阻塞io。包括java.io包下,和java.net包下的内容。
2、同步非阻塞io。主要指java.nio包下的内容。
3、异步io。
我们看到了一些名词。关于同步异步,阻塞非阻塞的概念,需要先澄清一下。
同步异步,描述的是被调用者,也就是操作系统。同步情况,那么操作系统收到请求会执行,执行后再响应。异步情况,操作系统收到请求会立刻响应,再执行。
阻塞非阻塞,描述的是调用者。阻塞情况,那么当调用不成功,该线程就会等待。非阻塞情况,当调用不成功,就继续执行后续逻辑。
再了解一下取数的过程。所有取数,都分两个阶段。
1.从硬盘到内核空间中。
2.从内核空间到用户空间。
了解了一些前提概念,接下来继续看Java中的三种IO的思想。
一、同步阻塞io。
最原始也是最易懂的io模型。它通过read调用取数,如果read调用没获取数据,就一直等。
第一类分法:字节流和字符流。字节流有InputStream,OutputStream,处理二进制。字符流有Reader,Writer,处理文本信息。
第二类分法:读写方向。从硬盘读到内存,为输入,有InputStream和Reader。反之为输出,有OutputStream和Writer。
第三类分法:节点流和处理流。节点流是指直接链接到实际的数据源。处理流则不直接接触数据源,而是包装一个节点流。
还有一些特殊的IO流,AudioInputStream、ZipInputStream。用来处理音频压缩文件等流,位于其他包而不在java.io包下。
二、多路复用,同步非阻塞nio。
它明显地分成了两个阶段。第一个阶段,通过select调用,判断内核是否将数据准备好,select可以同时查看多个channel,所以称为多路复用。当发现某个channel准备好了,就通过read调用,将数据从内核空间拷贝到用户空间。
有这么几个抽象。Channel、Selector、Buffer。
三、异步aio。
会注册一个回调函数,等到操作系统数据完毕后再通知相应线程来处理。
总结:
写业务代码的同学基本上用不上这些,但是当我们看任何中间件源码的时候,都必然有连接器这个组件。追求高性能的中间件必然是用nio或者aio来实现。
对取数的过程,类似kafka会有zero-copy机制,就是在内核空间向用户空间拷贝这一步会合并。
本节我们从概念上先行了解,后续会继续展开nio和aio的内容。