nio ---基本概念和使用

一、序言 

       关于NIO 相关介绍也很多了,这里主要目的还是通过自己的学习,分享一部分自己的理解,计划从基本概念到原理、到使用、到一些源码底层的分析,也回顾和总结自己的学习历程,今天先介绍概念。

 

 

二、NIO介绍

       NIO 从JDK1.4 提出的,介绍是为了弥补IO的不足,提供了更高效的方式,提出一个通道(channel)的概念。源于IO的不足,还在在于它始终以流的形式对数据的传输和接受,当然NIO也差不多,但是NIO 提供了一种内存映射数据的方式,

       简单的理解是:IO 原来是用固定的水管传输和接受水源,NIO可以提供一种用桶的方式传输和接受水源。比如在取水过程中,IO可以让接水,NIO可以直接一次打满一桶水,从效率上看,很明显的,当然这仅仅是一个好处,其他的我们后面解释。

 

三、通道和缓冲区

       缓冲区(buffer):这个很好理解,即使IO也有这个概念,就就像我们读、写文件的时候,不会拿到一个字节,就对文件进行读、写操作,一般情况会建立一个缓存区数组,比如new byte[1024*4],然后将缓冲区的数据一次操作。在NIO中这里的原理其实一样的,可能细节实现上有些区别。

 

       通道(channle): 这玩意儿,它需要从缓冲区获取数据,缓冲区也可以从通道里面提取数据,相当于我另外开辟了一个空间来存放我的数据,而且是双向的,对里面数据的掌控性也更好,好吧, 这些都是空话,实践出真知,我们后面实践的时候再对它进行细致的描述。

 

 

四、JDK 和 代码示例

        全理论化的东西,是很烦人,即使写得很大白话,还是代码看着亲切。

        1.先看看buffer 缓冲区: 这个其实也是装老的byte[] ,先看看我们将文件流放到byte 数组的写法区别

       

		// 这是原始方式之一
                FileInputStream is = new FileInputStream(name);
		// 这个区间可以自己定义
		byte[] buff = new byte[is.available()];
		is.read(buff);
		return buff;

   

		// 这是新方式
		FileInputStream f = new FileInputStream(name);
		// 获得通道,这里用了API 没公布的一些类,组合而成,有时间可以去看                          // 看源码
		FileChannel channel = f.getChannel();
		// 创建一个缓冲区
		ByteBuffer buffer = ByteBuffer.allocate(f.available());
                // 从通道读取放入缓冲区
		channel.read(buffer);
                // 注意,这里如果是分配的直接缓冲区 ,此方法会出错的,可以看源码
                byte[] bytes = buffer.array();

   

    上面的例子,其实你也不知道有啥好处,仅仅熟悉一下必要的步骤:通道<---> 缓冲区

    下面我们来看看文件复制的操作:

     

	// 原始方式的文件复制
	public static void copyFile(String orgFile,String targetFile) throws Exception{
		FileInputStream in = new FileInputStream(orgFile);
		FileOutputStream out = new FileOutputStream(targetFile);
		byte[] buff = new byte[1024*8];
		int len = 0;
		while((len = in.read(buff)) != -1){
			out.write(buff,0,len);
		}
	}

    

    

  // 这是利用通道 缓冲区 的方式,和上面差不多
   public static void copyFile2(String orgFile,String targetFile) throws Exception{
		FileInputStream in = new FileInputStream(orgFile);
		FileOutputStream out = new FileOutputStream(targetFile);
		FileChannel  orgChannel = in.getChannel();
		FileChannel tarChannel = out.getChannel();
		ByteBuffer buffer = ByteBuffer.allocate(1024*8);
		int len = 0;
		while((len = orgChannel.read(buffer)) != -1){
			buffer.flip();
			tarChannel.write(buffer);
			buffer.clear();
		}
	}

 

    

	// 这个是直接用API 的方式
	public static void copyFile3(String orgFile,String targetFile) throws Exception{
		FileInputStream in = new FileInputStream(orgFile);
		FileOutputStream out = new FileOutputStream(targetFile);
		FileChannel  orgChannel = in.getChannel();
		FileChannel tarChannel = out.getChannel();
		orgChannel.transferTo(0, orgChannel.size(), tarChannel);
	}

 

     上面测试我用了一个大于JVM 限制的文件复制,结果是最后一种最快啦~。~(小文件就算了)

      关于通道复制速度的解释:http://www.ibm.com/developerworks/cn/java/j-zerocopy/ 很详细

 

     2.关于通道这个东西我的理解是:就像给我们数据源和地点之间加了一个大的用于传输的通道,这不是简单的让字节流通过的通道,而是里面允许我们做更多的检测、加速、返回等等操作的通道,后面分析源码的时候再体会吧。

     

     关于缓冲区要说到的几个元素和方法,比如我们刚才用到的flip和clear。首先要理解这个缓冲区其实就是一个byte[] 数组的空间,里面有这几个元素:

     Capacity:这表示容量,也就是说我数组的最大长度

    position: 相当于指针,当我们操作数组里面元素的时候,这个会跟着移动,记录我们的位置,方便我们记录下次要用数据。

    mark:标记位置,和事务的回滚位置差不多,相当于我们在这个位置记录一下,下一次我可以返回到这个位置干事。

    limit :我们只能读操作到位置,比如我10长度的数组,只有前面6个又数据,那么我就设置只能操作前面6个有效的。

   关于基本的东西可以看看源码,很容易,也可以看看这文章:

   http://www.ibm.com/developerworks/cn/education/java/j-nio/section5.html

 

小结:

     1.这里仅仅介绍下NIO 的使用基本情况,没有深入,它的优势还在于它的不阻塞模式,和Selector管理模式,后面会根据原理和源码分析。

    

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值