zoukankan      html  css  js  c++  java
  • 深入Java网络编程与NIO(二)

    Java IO流总结

    Java IO类图

    • 按照操作方式分类:
      Java IO类图

    Java IO按照操作单元分,可以分为字节流InputStream、OutputStream和字符流Reader、Writer

    • 字节流和字符流的区别:
      字节流在JDK1.0中就被引进了,用于操作包含ASCII字符的文件。JAVA也支持其他的字符如Unicode,为了读取包含Unicode字符的文件,JAVA语言设计者在JDK1.1中引入了字符流。ASCII作为Unicode的子集,对于英语字符的文件,可以可以使用字节流也可以使用字符流。

    • 按照操作对象分类
      Java IO类图2

    • 总结:
      Java IO这样设计的原因是让每一个类都负责不同的功能。共涉及40多个类,这些类看上去很杂乱,但实际上很有规则,而且彼此之间存在非常紧密的联系,
      Java IO流的40多个类都是从如下4个抽象类基类中派生出来的。

    InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。
    OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。

    Java IO

    1.文件IO

    JAVA 中文件IO原生的读写方式大概可以被分为三种:普通IO,FileChannel(文件通道),MMAP(内存映射)。区分他们也很简单,例如 FileWriter,FileReader 存在于 java.io 包中,他们属于普通IO;FileChannel 存在于 java.nio 包中,属于 NIO 的一种,但是注意 NIO 并不一定意味着非阻塞,这里的 FileChannel 就是阻塞的;较为特殊的是后者 MMAP,它是由 FileChannel 调用 map 方法衍生出来的一种特殊读写文件的方式,被称之为内存映射。

    FileChannel 和 MMAP

    使用 FIleChannel 的方式:

    FileChannel fileChannel = new RandomAccessFile(new File("db.data"), "rw").getChannel();
    

    获取 MMAP 的方式:

    MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, fileChannel.size()
    );
    

    FileChannel 大多数时候是和 ByteBuffer 这个类打交道,你可以将它理解为一个 byte[] 的封装类,提供了丰富的 API 去操作字节,不了解的同学可以去熟悉下它的 API。值得一提的是,write 和 read 方法均是线程安全的,FileChannel 内部通过一把 privatefinalObjectpositionLock=newObject(); 锁来控制并发。

    一个问题:FileChannel 是直接把 ByteBuffer 中的数据写入到磁盘吗?
    思考几秒…答案是:NO。
    ByteBuffer 中的数据和磁盘中的数据还隔了一层,这一层便是 PageCache,是用户内存和磁盘之间的一层缓存。我们都知道磁盘 IO 和内存 IO 的速度可是相差了好几个数量级。我们可以认为 filechannel.write 写入 PageCache 便是完成了落盘操作,但实际上,操作系统最终帮我们完成了 PageCache 到磁盘的最终写入,所以 FileChannel 会提供一个 force() 方法,用于通知操作系统进行及时的刷盘。
    所以,当我们使用 FileChannel 进行读操作时,同样经历了:磁盘->PageCache->用户内存这三个阶段。

    MMAP
    MMAP 的作用:内存映射文件,我们之后对内存中 MappedByteBuffer 做的任何操作,都会被最终映射到文件之中,

    mmap 把文件映射到用户空间里的虚拟内存,省去了从内核缓冲区复制到用户空间的过程,文件中的位置
    在虚拟内存中有了对应的地址,可以像操作内存一样操作这个文件,相当于已经把整个文件放入内存,但在
    真正使用到这些数据前却不会消耗物理内存,也不会有读写磁盘的操作,只有真正使用这些数据时,也就是
    图像准备渲染在屏幕上时,虚拟内存管理系统 VMS 才根据缺页加载的机制从磁盘加载对应的数据块到物理
    内存进行渲染。这样的文件读写文件方式少了数据从内核缓存到用户空间的拷贝,效率很高

    MMAP 操作大文件性能比 FileChannel 搞出一个数量级!

    参考资料:

    Java IO常见面试题
    文件IO操作的最佳实践

  • 相关阅读:
    BZOJ 2034 【2009国家集训队】 最大收益
    vijos P1780 【NOIP2012】 开车旅行
    BZOJ 2115 【WC2011】 Xor
    BZOJ 3631 【JLOI2014】 松鼠的新家
    BZOJ 4717 改装
    BZOJ 2957 楼房重建
    BZOJ 4034 【HAOI2015】 T2
    BZOJ 1834 【ZJOI2010】 network 网络扩容
    BZOJ 2440 【中山市选2011】 完全平方数
    BZOJ 2733 【HNOI2012】 永无乡
  • 原文地址:https://www.cnblogs.com/shawshawwan/p/10104493.html
Copyright © 2011-2022 走看看