读书笔记-《Java NIO》:第三章 通道(3)

来源:互联网 发布:素数java 编辑:程序博客网 时间:2024/06/02 00:36

言归正传,今天来看看通道中的文件通道~~~


焦点1: File Channel在整个I/O体系中的位置



先复习下I/O的简单分类,I/O广义上分为File I/O和Stream I/O, FileChannel文件通道,顾名思义就是服务于File I/O的。

FileChannel在Channel类图的位置,从图中可以看出FileChannel实现了ByteChannel,证明FileChannel是一个双向Channel,因为它实现了ByteChannel(ByteChannel实现了ReadableByteChannel和WritableByteChannel),FileChannel还实现了ScatteringByteChannel和GatheringByteChannel,证明FileChannel支持Scatter和Gather功能。


焦点2:File I/O和Stream I/O的区别是什么?



要想理清File I/O,得先知道File是个什么东东?下面的这些文档,就是我们要说的File,我们知道这些文档是存在硬盘上的。

那什么是硬盘,下面的就是硬盘,操作系统呈献给用户的界面如下图。

但上面的是操作系统的软件呈现,真正的硬盘实体是下图这个东东,把电脑的机箱打开,会看到这个东东。

硬盘并不知道什么是文件,硬盘只知道存储的是字节,至于这些字节怎么被解释,怎么被组织,它不管这些。硬盘的单位存储单元是扇区,一个扇区是512字节。也就是说想要获取硬盘的数据,每次存取的最小单元是512字节。但文件可以是任意大小,如下图。

这是怎么做到的呢?因为在硬盘和文件之间有一个文件系统文件系统负责组织和解释硬盘中存储的字节。比如哪些字节是表示"新建文本文档.txt",哪些字节是表示"新建文本文档.txt(2)",表示同一个文件的字节空间,在硬盘上不一定是连续的,有可能是分散的。

因为每次都要从磁盘上取或写单个扇区的倍数(512 byte的倍数),所以文件I/O也就是File I/O是面向块的。


但并不是所有的I/O都是面向块的,流I/O就不是。

流I/O有以下几个特点:

1)字节流必须顺序存取,如控制台设备,打印机端口和网络连接;

2)经常用于间歇性输入,就是一会儿有输入,一会儿没输入,输入的间隔也不固定;因为是间歇性输入,就引入了“就绪性选择”这个概念,操作系统可以检测一系列流,如果有流就绪,操作系统就可以返回就绪状态给进程。

3)不是面向块的。


焦点3:FileChannel API



FileChannel本身是一个抽象类。

这里讲下position()方法,positon的值决定了接下来文件中的哪一处数据会被读或写。

position()方法有两个:

public abstract long position() throws IOException;

// 返回当前文件的position值;

public abstract FileChannel position(long newPosition) throws IOException;

// 将通道的position值设定为指定的值;


如果将position设置为一个超出文件大小的值,会出现什么情况呢?

1)如果此时执行read(),那么会返回一个文件尾的条件;

2)如果执行write(),会引起文件增长以容纳写入的字节,这就可能会引入“文件空洞”问题。


焦点4: 文件的锁定



FileChannel实现的文件锁模型,锁的对象是文件而不是通道或线程,这意味着文件锁不适用于判优同一台Java虚拟机上的多线程发起的访问。


如果一个线程在一个文件上获得了独占锁,然后第二个线程利用一个单独单开的通道来请求该文件的独占锁,第二个线程的请求会被批准。如果两个线程运行在不同的Java虚拟机上,那么第二个线程会阻塞。


锁与文件关联,而不是与通道关联。我们使用锁来来判优外部进程,而不是判定同一个Java虚拟机的线程。


如果想控制同一个虚拟机上运行的多个线程的并发访问,那么需要实施你自己的,轻量级的锁方案,FileChannel提供了一些API。

带参数的lock方法,可以设定要锁的区域,不带参数的lock是锁整个文件,tryLcok是lock的非阻塞版本,如果请求的锁不能立即返回,lock会阻塞,而tryLock会立即返回一个null。


今天先到这儿,明天继续( ^_^ )


原创粉丝点击