下面是自己学习整理Java IO/NIO的总结,期间浏览了网上很多优秀的总结分析文章,一并贴在这里供大家学习参考。IO的知识点学习大概分为以下几个部分:
-
概念理解
-
熟悉Java IO API
-
熟悉Java NIO API
-
系统的IO优化
-
优秀IO/NIO开源框架学习
第一部分:概念理解
什么是IO?IO就是Input(输入)和Output(输出),比如:从文件系统中读取某个文件的内容,一台服务器将数据发送到另一台服务器,这些都是IO操作。IO研究的问题无非就是把什么样的数据(数据格式)以什么数据形式发送到哪里的问题。
第二部分:熟悉Java IO API
-
基于字节操作的 I/O 接口:InputStream 和 OutputStream
-
基于字符操作的 I/O 接口:Writer 和 Reader
-
基于磁盘操作的 I/O 接口:File(重点)
-
基于网络操作的 I/O 接口:Socket(重点)
前两组主要是根据传输数据的数据格式,后两组主要是根据传输数据的方式,虽然 Socket 类并不在 java.io 包下,但是它的实质也是IO。
第三部分:熟悉Java NIO API
Java NIO的出现是为了弥补IO在很多方面的不足。Java NIO是基于Buffer和Channel的。他们最主要的区别在于:
IO | NIO |
Stream oriented(面向流) | Buffer oriented(面向buffer) |
Blocking IO(阻塞) | Non blocking IO(非阻塞) |
Selector(选择器) |
传统IO操作状态无法记录,不知道读/写了多少,还有多少是有效字节,下次从哪里开始读/写,NIO则很好的解决了这个问题,使得操作更加精确可控,而且读写效率更高。
NIO里关键的Buffer实现:
-
ByteBuffer
-
CharBuffer
-
IntBuffer
-
ShortBuffer
-
LongBuffer
-
FloatBuffer
-
DoubleBuffer
-
MappedbyteBuffer
NIO里关键的Channel实现:
-
FileChannel:从文件中读写数据
-
DatagramChannel:通过UDP 读写网络中的数据
-
SocketChannel:通过TCP读写网络中的数据
-
ServerSocketChannel:可以监听新进来的TCP连接,像web 服务器那样。对每一个新进来得连接都会创建一个SocketChannel。
其它重要的类:
-
Selector
-
SelectionKey
-
Channels
重要概念的理解:同步、异步、阻塞、非阻塞
buffer的理解:capacity、limit、position、mark
第四部分:系统的IO优化
磁盘IO优化:
-
增加缓存,减少磁盘访问次数
-
优化磁盘的管理系统,设计最优的磁盘访问策略,以及磁盘的寻址策略,这里是在底层操作系统层面考虑的。
-
设计合理的磁盘存储数据块,以及访问这些数据块的策略,这里是在应用层面考虑的。如我们可以给存放的数据设计索引,通过寻址索引来加快和减少磁盘的访问,还有可以采用异步和非阻塞的方式加快磁盘的访问效率。
-
应用合理的 RAID 策略提升磁盘 IO,
网络IO优化:
-
一个是减少网络交互的次数:要减少网络交互的次数通常我们在需要网络交互的两端会设置缓存,比如 Oracle 的 JDBC 驱动程序,就提供了对查询的 SQL 结果的缓存,在客户端和数据库端都有,可以有效的减少对数据库的访问。关于 Oracle JDBC 的内存管理可以参考《 Oracle JDBC 内存管理》。除了设置缓存还有一个办法是,合并访问请求:如在查询数据库时,我们要查 10 个 id,我可以每次查一个 id,也可以一次查 10 个 id。再比如在访问一个页面时通过会有多个 js 或 css 的文件,我们可以将多个 js 文件合并在一个 HTTP 链接中,每个文件用逗号隔开,然后发送到后端 Web 服务器根据这个 URL 链接,再拆分出各个文件,然后打包再一并发回给前端浏览器。这些都是常用的减少网络 I/O 的办法。
-
减少网络传输数据量的大小:减少网络数据量的办法通常是将数据压缩后再传输,如 HTTP 请求中,通常 Web 服务器将请求的 Web 页面 gzip 压缩后在传输给浏览器。还有就是通过设计简单的协议,尽量通过读取协议头来获取有用的价值信息。比如在代理程序设计时,有 4 层代理和 7 层代理都是来尽量避免要读取整个通信数据来取得需要的信息。
-
尽量减少编码:通常在网络 I/O 中数据传输都是以字节形式的,也就是通常要序列化。但是我们发送要传输的数据都是字符形式的,从字符到字节必须编码。但是这个编码过程是比较耗时的,所以在要经过网络 I/O 传输时,尽量直接以字节形式发送。也就是尽量提前将字符转化为字节,或者减少字符到字节的转化过程。
-
根据应用场景设计合适的交互方式:所谓的交互场景主要包括同步与异步阻塞与非阻塞方式
第五部分:优秀IO/NIO开源框架学习
目前开源社区比较优秀的IO/NIO开源框架有:Apache MINA、Netty
通过学习优秀的开源框架,我们可以升华我们所学,进一步的加深对IO/NIO的理解。以下是一些优秀的参考博客:
1、Java NIO系列教程(重点推荐):
http://www.iteye.com/magazines/132-Java-NIO
2、深入分析 Java I/O 的工作机制(重点推荐):
https://www.ibm.com/developerworks/cn/java/j-lo-javaio/
3、深入分析Java中的中文编码问题(重点推荐):
https://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/
4、Java深入历险——Java IO
http://www.infoq.com/cn/articles/cf-java-i-o
5、Java NIO分析
https://askingwindy.gitbooks.io/gitbook-java-interview-note/content/io/syn-ays-blocked/nio.html
6、Java NIO原理图文分析
http://weixiaolu.iteye.com/blog/1479656