MyException - 我的异常网
当前位置:我的异常网» 编程 » java nio 通路(二)

java nio 通路(二)

www.MyException.Cn  网友分享于:2014-08-05  浏览:0次
java nio 通道(二)

本文章来源于我的个人博客: java nio 通道(二)


一,文件通道

    文件通道总是阻塞式的,因此不能被置于非阻塞模式。

    FileChannel对象是线程安全的。多个进程可以在同一个实例上并发调用方法而不会引起任何问题,不过非所有的操作都是多线程的。影响通道位置或者影响文件大小的操作都是单线程的。通过FileChannel实例看到的某个文件的视图同通过一个外部的非java进程看到的该文件的视图可能一致也可能不一致。

    创建文件通道:

RandomAccessFile randomAccessFile = new RandomAccessFile(filename,"r");
//设置读取文件的位置
randomAccessFile.seek(1000);
//创建文件通道
FileChannel fileChannel = randomAccessFile.getChannel();
System.out.println(fileChannel.position());  // print 1000
randomAccessFile.seek(500);
System.out.println(fileChannel.position());  //print 500
fileChannel.position(200);  
System.out.println(randomAccessFile.getFilePointer());  //print 200


二,文件锁定(FileLock)

    大家都知道,文件锁分为独占所和共享锁。独占锁是当有一个锁拥有了文件的操作权限之后,其它的访问者都必须等待当前的操作者完成才能操作文件;而共享锁是所有的访问者都可以同时使用该文件。独占锁最重要用于文件的写,而共享锁用于文件的读。

    java的文件锁只与文件关联,而不是与通道关联。文件锁旨在在进程级别上判优文件访问,比如在主要的程序组件之间或者在继承其他供应商的组件时。如果需要控制多个java线程的并发访问,就需要自己做锁定方案。

    再FileChannel类中有四个请求锁的方法,分别为:

public final FileLock lock();
public abstract FileLock lock(long position, long size, boolean shared);
public final FileLock tryLock();
public abstract FileLock tryLock(long position, long size,boolean shared);

    两个带参数的请求所方法的意思是指定需要锁定文件的区域位置,并设置这个锁是否为共享锁,注意,如果要请求一个独占锁,则文件必须是以写模式打开的,锁区域的size值可以超出文件尾部,这样可以提前锁定需要待写入的文件数据区域,也可以锁定一个不包含任何内容的文件内容区域。不带参数的请求方法是请求整个文件的独占锁,也就是使用无参数的请求方法获取的锁,会阻塞后来的操作,只当这个锁定的访问者执行完它的操作为止。

    请一定要记住,在操作完成之后,一定要release锁,不然将可能导致程序奔溃或者死锁现象。


三,内存映射文件(MappedByteBuffer file):

    FileChannel类提供了一个名为map()的方法,该方法可以在一个打开的文件和一个特殊类型的ByteBuffer之间建立一个虚拟内存映射MappedByteBuffer。这个对象和基于内存的缓冲区类似,只不过该对象的数据元素存储在磁盘上的一个文件中。调用get()方法会从磁盘文件中获取数据,此数据反映该文件的当前内容,即使在映射建立之后文件已经被一个外部进程做了修改,也会同步到该对象所在的内存视图中;当然该对象的put()方法也会同步更新此文上的文件,即对文件的改变其他的访问者也是可见的。

    通过内存映射机制来访问一个文件会比使用常规方法读写高效得多,甚至比使用通道的效率都高。因为不需要做明确的系统调用,那会很消耗时间,更重要的是,操作系统的虚拟内存可以自动缓存内存页,这些内存页是系统内存来缓存的,所以不会消耗java虚拟机内存堆。(注:这段话因为涉及了操作系统的内存机制,博主也不怎么理解,博主的想法是只要知道使用这个对象会脱离JVM的内存堆,剔除了JVM这个中间桥梁)

    FileChannel类调用内存映射的方法如下:

public abstract MappedByteBuffer map(MapMode mode, long position, long size);
public static class MapMode{
    public static final MapMode READ_ONLY;
    public static final MapMode READ_WRITE;
    //代表需要一个写时拷贝的映射。意味着通过put()方法所做的任何修改都会导致产生一个私有的数据拷贝并且
    //该拷贝中的数据只有MappedByteBuffer实例可以看到。该过程不会对地城文件做任何修改,而且一旦缓冲
    //区被拖到垃圾收集动作,那些修改的数据都会丢失。使用此模式时,其它的操作者对文件的修改,也都能反映
    //到这个内存映射区域,除非该缓冲区已经修改了文件上的同一区域。
    public static final MapMode PRIVATE;
}

    这个方法的第一个参数是设定这个内存映射区域是只读还是只写或者私有方式访问,第二个参数和第三个参数一起决定了内存映射的区域。要注意,这个内存映射的锁方式和文件锁的范围机制是不一样的。如果给这个内存映射对象的size的值设置为Integer.MAX_VALUE,则这个文件的大小会扩张到超过2.1GB,也就是说,这个内存映射文件的锁定区域如果超出了文件的大小,那么它会自动给这个设定的区域加入数据。

    MappedByteBuffer对象被创建之后,就不会受通道的关闭影响,也就是如果关闭相关联的FileChannel不会破坏映射,只有丢弃缓冲区对象本身才会破坏该映射。

    MappedByteBuffer类有以下的几个独有方法:

public final MappedByteBuffer load();
public final boolean isLoaded();
public final MappedByteBuffer force();

    当为一个文件建立虚拟内存映射之后,文件数据通常不会因此被从磁盘读取到内存(这取决于操作系统)。该过程类似于打开一个文件:文件先被定位,然后一个文件句柄会被创建,当准备好之后,就可以通过句柄来访问文件数据。对于映射缓冲区,虚拟内存系统将根据需要来把文件中相应区块的数据读进来。这个页验证或防错过程需要一定的时间,因为将文件数据读取到内存需要一次或多次磁盘访问。

    load()方法会加载整个文件以使它常驻内存。但是调用此方法是一个代价高昂的操作,因为它会导致大量的页调入。force()方法会强制将映射缓冲区上的更改应用到永久磁盘存储器上。

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;


public class TestMappedByte {

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		 File file = new File("/home/lifeix/3.txt");
        if(!file.exists()) {
            file.createNewFile();
        }
        String str = "jiang fuqiang is cool
";
        //此类没有追加文件选项,如果需要追加,则需要调用fos.seek(int)方法
        RandomAccessFile fos = new RandomAccessFile(file,"rws"); 
        FileChannel fc = fos.getChannel();
        ByteBuffer bb = ByteBuffer.allocateDirect(str.length());
        bb.put(str.getBytes());
        bb.flip();
        fc.write(bb);
        bb.clear();
        
        //如果这里不使用fc.position(),则此处写入的数据会覆盖掉上面写入的数据,这是一种自己实现的文件追加方式,
        //此处不能用FileOutputStream,不然会报错
        MappedByteBuffer mbb = fc.map(MapMode.READ_WRITE, fc.position(), 1024);
        mbb.put(str.getBytes());
        mbb.force();
        mbb.clear();
        fc.close();
        fos.close();
        
        FileInputStream fis = new FileInputStream(file);
        FileChannel fc1 = fis.getChannel();
        MappedByteBuffer mbb1  = fc1.map(MapMode.READ_ONLY, 0, fc1.size());
        byte[] b = new byte[mbb1.remaining()];
        mbb1.get(b);
        System.out.println(new String(b));
        fc1.close();
        fis.close();
        
	}

}


文章评论

程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
Java程序员必看电影
Java程序员必看电影
程序员必看的十大电影
程序员必看的十大电影
如何成为一名黑客
如何成为一名黑客
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
鲜为人知的编程真相
鲜为人知的编程真相
旅行,写作,编程
旅行,写作,编程
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
程序员都该阅读的书
程序员都该阅读的书
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
为什么程序员都是夜猫子
为什么程序员都是夜猫子
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
老程序员的下场
老程序员的下场
编程语言是女人
编程语言是女人
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
漫画:程序员的工作
漫画:程序员的工作
我的丈夫是个程序员
我的丈夫是个程序员
一个程序员的时间管理
一个程序员的时间管理
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
程序员和编码员之间的区别
程序员和编码员之间的区别
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
那些争议最大的编程观点
那些争议最大的编程观点
程序员的鄙视链
程序员的鄙视链
我是如何打败拖延症的
我是如何打败拖延症的
每天工作4小时的程序员
每天工作4小时的程序员
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
总结2014中国互联网十大段子
总结2014中国互联网十大段子
10个调试和排错的小建议
10个调试和排错的小建议
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
程序员应该关注的一些事儿
程序员应该关注的一些事儿
代码女神横空出世
代码女神横空出世
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有