• java特种兵读书笔记(4-2)——java通信之IO与内存


    常规IO操作过程


    java程序普通的IO过程,都会经历从Kernel到JVM的内存拷贝。

    例如做一次文件拷贝,一般会开启一个输入流,将文件读取到JVM内存中,然后开启一个输出流,将内存中数据输出到另一个文件中(一个文件->kernel->JVM内存->另一个文件)。

    不是磁盘->磁盘,不是磁盘->内存,而是会经历一个内核区。

    拷贝内存速度很快,但是反复大量拷贝也有很大开销。可以跳过JVM拷进拷出。

    高层次抽象与低层次抽象的效率问题


    低层次抽象的拷贝未必就比高层次抽象的拷贝快多少,因为在IO直接交互的位置产生瓶颈(最终磁盘到OS的页面交换速度本身的瓶颈,所以有可能数据堵在kernel,而没有写入到终端)。

    内存映射


    这块区域直接映射到磁盘上,用FileChannel.map()在磁盘对应位置直接分配一块空间,类似虚拟内存,负责返回一个MappedByteBuffer类型的对象(本质也是DirectByteBuffer,只是它直接映射到磁盘上),这并不代表它没有缓冲区,只是通过OS来控制。此时对该ByteBuffer直接写入数据,就直接写入磁盘了,省去了拷贝的过程。

    JDK1.7之后,使用Files.copy()方法简单很多。

    Buffer


    Cache是将数据就近存储,存取方便。

    Buffer通常与IO相关,是IO交互过程的一个缓冲区,达到一次交互一批信息而不是一个字节信息的目的。

    BufferXXXStream和BufferReader/Writer就是Buffer使用代表,使用java的一个数组来完成,将对应的流修饰后,使得输入输出过程自动产生Buffer功能。

    HeapByteBuffer在java heap中分配空间,DirectByteBuffer在C heap中分配空间。

    flip()方法将limit设置为当前position位置,将position设置为0,将mark设置为-1。该动作为了获取Buffer中[0,position]当中的所有数据(即Buffer中现有的所有数据)。flip将limit放在数据有效位置的末尾,以便于读取所有有效数据。

    clear()将limit放在总容量最后的位置,以便于重新写入数据。但是此时数据还在,可以从这里面读取数据。

    remaining()是limit-position的值,即剩余空间。

    FileChannel加锁


    FileChannel可以通过FileXXXStream,RandomAccessFile的getChannel()方法来获得。

    它有加锁功能,lock()方法如果拿不到锁会阻塞,tryLock()方法拿不到锁会返回null,拿到了会返回FileLock对象。

    需要关闭锁的时候,使用release()即可。

  • 相关阅读:
    RPC通信基本原理 -- 浅析RPC远程过程调用基本原理
    我要涨知识——TypeScript 经典高频面试题(二)
    ES 搜索引擎
    基于Docker和MongoDB部署NodeBB论坛系统
    【毕业设计】20-基于单片机的指纹识别系统设计(原理图工程+源代码工程+实物操作图+答辩论文+答辩PPT)
    数据结构:链表(2),链表面试题
    LDR6023AQ-PDHUB最简外围成本低搂到底就是干
    xCode14.3.1运行MonkeyDev出现“Executable Not Found“的解决办法
    nodejs-express项目初始化
    第1章 入门
  • 原文地址:https://blog.csdn.net/xocupid/article/details/125601829