您的位置:首页 > 编程语言 > Java开发

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

2016-01-18 15:45 337 查看
常规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()即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: