(由于java的IO这一块,基础的字节流字符流IO好理解,在JavaGuide的开源笔记里有较好的讲解,就copy过来。而NIO AIO又是出了名的难以理解和难用,故只了解了其思想,学会了使用,不深究其源码和实现的底层细节,在之后系统了学习了将NIO封装更好的netty之后再进行补充)
IO流学习总结
一 Java IO,硬骨头也能变软
(1) 按操作方式分类结构图:
(2)按操作对象分类结构图
二 java IO体系的学习总结
-
IO流的分类:
- 按照流的流向分,可以分为输入流和输出流;
- 按照操作单元划分,可以划分为字节流和字符流;
- 按照流的角色划分为节点流和处理流。
-
流的原理浅析:
java Io流共涉及40多个类,这些类看上去很杂乱,但实际上很有规则,而且彼此之间存在非常紧密的联系, Java Io流的40多个类都是从如下4个抽象类基类中派生出来的。
- InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。
- OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。
-
常用的io流的用法
流的设计模式
看起来这些流的种类繁多,其实所有的流都是基于以上的4个流的基类,在其基础上进行的扩展。
运用到了典型的装饰器模式。
可以参看这篇博文讲明白了装饰器模式的实现过程
三 Java IO面试题
NIO与AIO学习总结
一 Java NIO 概览
-
NIO简介:
Java NIO 是 java 1.4, 之后新出的一套IO接口NIO中的N可以理解为Non-blocking,不单纯是New。
-
NIO的特性/NIO与IO区别:
- 1)IO是面向流的,NIO是面向缓冲区的;
- 2)IO流是阻塞的,NIO流是不阻塞的;
- 3)NIO有选择器,而IO没有。
-
读数据和写数据方式:
-
从通道进行数据读取 :创建一个缓冲区,然后请求通道读取数据。
-
从通道进行数据写入 :创建一个缓冲区,填充数据,并要求通道写入数据。
-
-
NIO核心组件简单介绍
- Channels
- Buffers
- Selectors
二 Java NIO 之 Buffer(缓冲区)
-
Buffer(缓冲区)介绍:
- Java NIO Buffers用于和NIO Channel交互。 我们从Channel中读取数据到buffers里,从Buffer把数据写入到Channels;
- Buffer本质上就是一块内存区;
- 一个Buffer有三个属性是必须掌握的,分别是:capacity容量、position位置、limit限制。
-
Buffer的常见方法
- Buffer clear()
- Buffer flip()
- Buffer rewind()
- Buffer position(int newPosition)
-
Buffer的使用方式/方法介绍:
- 分配缓冲区(Allocating a Buffer):
ByteBuffer buf = ByteBuffer.allocate(28);//以ByteBuffer为例子
- 写入数据到缓冲区(Writing Data to a Buffer)
写数据到Buffer有两种方法:
1.从Channel中写数据到Buffer
int bytesRead = inChannel.read(buf); //read into buffer.
2.通过put写数据:
buf.put(127);
-
Buffer常用方法测试
说实话,NIO编程真的难,通过后面这个测试例子,你可能才能勉强理解前面说的Buffer方法的作用。
三 Java NIO 之 Channel(通道)
- Channel(通道)介绍
- 通常来说NIO中的所有IO都是从 Channel(通道) 开始的。
- NIO Channel通道和流的区别:
- FileChannel的使用
- SocketChannel和ServerSocketChannel的使用
- ️DatagramChannel的使用
- Scatter / Gather
- Scatter: 从一个Channel读取的信息分散到N个缓冲区中(Buufer).
- Gather: 将N个Buffer里面内容按照顺序发送到一个Channel.
- 通道之间的数据传输
- 在Java NIO中如果一个channel是FileChannel类型的,那么他可以直接把数据传输到另一个channel。
- transferFrom() :transferFrom方法把数据从通道源传输到FileChannel
- transferTo() :transferTo方法把FileChannel数据传输到另一个channel
四 Java NIO之Selector(选择器)
- Selector(选择器)介绍
- Selector 一般称 为选择器 ,当然你也可以翻译为 多路复用器 。它是Java NIO核心组件中的一个,用于检查一个或多个NIO Channel(通道)的状态是否处于可读、可写。如此可以实现单线程管理多个channels,也就是可以管理多个网络链接。
- 使用Selector的好处在于: 使用更少的线程来就可以来处理通道了, 相比使用多个线程,避免了线程上下文切换带来的开销。
- Selector(选择器)的使用方法介绍
- Selector的创建
Selector selector = Selector.open();
- 注册Channel到Selector(Channel必须是非阻塞的)
channel.configureBlocking(false); SelectionKey key = channel.register(selector, Selectionkey.OP_READ);
-
SelectionKey介绍
一个SelectionKey键表示了一个特定的通道对象和一个特定的选择器对象之间的注册关系。
-
从Selector中选择channel(Selecting Channels via a Selector)
选择器维护注册过的通道的集合,并且这种注册关系都被封装在SelectionKey当中.
-
停止选择的方法
NIO实现的demo
如上面两张图,实际上这里再select选择好了可以操作的channle后,只用了一个线程去处理各种accept和read等操作,实际上,可以根据不同的操作新建出不同的线程来处理accept和read,提高NIO的工作效率。再服务端实现了非阻塞。
实际上,在NIO中还有更加复杂的事件分发器(Reactor),将每个需要处理的通道交给其对应的处理者(Handle),这个需要开发人员事先进行注册,就更为复杂了,为了解决NIO的复杂性,出来了netty的框架,提供了简单的调用,让开发人员能专注于处理网络事务的逻辑,而不是NIO中复杂的细节开发。