A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 神马 中级黑马   /  2014-5-10 14:48  /  1385 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 神马 于 2014-5-10 16:49 编辑

对不住大家了,之前由于我的一个疏忽,导致我得出了错误的结论,自我批评中。。。

因为我的copy1、copy2、cpoy3的名字跟时间连在一起了,看起来就是一百多两百多三百多毫秒了,其实是几十毫秒。下面是我修改过后的帖子。


关于流缓冲区的效率探索,是从看毕向东老师的JAVA基础视频,产生的疑问开始的。毕老师视频里编写的字节流缓冲器MyBufferedInputStream复制一个Mp3是三百多毫秒,用JAVA库中的BufferedInputStream复制同样的Mp3是五百多毫秒。原理应该是一样的,为什么毕老师的要快,那JAVA库里的BufferedInputStream为什么不优化一下?经过网友的提示,我查看了BufferedInputStream.java的源代码,发现其中大多数的语句都是加了synchronized关键词修饰的,之前学过,同步判断是很影响效率的,尤其是示例程序中,每读取一个字节都要进行一次锁判断,所以导致了BufferedInputStream类的读取速度较慢,而毕老师的MyBufferedInputStream没有任何的同步判断,所以效率要高,速度明显快的多。如果文件更大一些,差距应该更大。

另外,我想研究一下有缓冲区到底比不用缓冲区快多少。于是我自己编了个小程序做试验,程序中的copyfile.txt是个两百多kb的文件。


  1. import java.io.*;
  2. class CopySpeedTest
  3. {
  4.         public static void main(String[] args)throws IOException
  5.         {
  6.                 long start=System.currentTimeMillis();        
  7.                 copy1();
  8.                 long end=System.currentTimeMillis();
  9.                 System.out.println("copy1用时:"+(end-start)+"毫秒");
  10.                 start=System.currentTimeMillis();        
  11.                 copy2();
  12.                 end=System.currentTimeMillis();
  13.                 System.out.println("copy2用时:"+(end-start)+"毫秒");
  14.                 start=System.currentTimeMillis();        
  15.                 copy3();
  16.                 end=System.currentTimeMillis();
  17.                 System.out.println("copy3用时:"+(end-start)+"毫秒");        
  18.         }
  19.         //使用FileReader的read方法一个字符一个字符读取
  20.         public static void copy1()throws IOException
  21.         {
  22.                 FileReader fr=new FileReader("copyfile.txt");
  23.                 FileWriter fw=new FileWriter("copyfile_copy.txt");
  24.                 int i;
  25.                 while((i=fr.read())!=-1)
  26.                 {
  27.                         fw.write(i);
  28.                         //fw.flush();
  29.                 }
  30.                 fr.close();
  31.                 fw.close();
  32.         }
  33.         //使用BufferedReader的read方法,一个字符一个字符读取
  34.         public static void copy2()throws IOException
  35.         {
  36.                 FileReader fr=new FileReader("copyfile.txt");
  37.                 BufferedReader br=new BufferedReader(fr);
  38.                 FileWriter fw=new FileWriter("copyfile_copy.txt");
  39.                 BufferedWriter bw=new BufferedWriter(fw);
  40.                 int i;
  41.                 while((i=br.read())!=-1)
  42.                 {
  43.                         bw.write(i);
  44.                         //bw.flush();
  45.                 }
  46.                 fr.close();
  47.                 bw.close();
  48.         }
  49.         //使用LineNumberReader的行读取方法
  50.         public static void copy3()throws IOException
  51.         {
  52.                 FileReader fr=new FileReader("copyfile.txt");
  53.                 LineNumberReader lnr=new LineNumberReader(fr);
  54.                 FileWriter fw=new FileWriter("copyfile_copy.txt");
  55.                 BufferedWriter bw=new BufferedWriter(fw);
  56.                 String line=null;
  57.                 while((line=lnr.readLine())!=null)
  58.                 {
  59.                         bw.write(line);
  60.                         //bw.flush();
  61.                 }
  62.                 fr.close();
  63.                 bw.close();
  64.         }
  65. }
复制代码
      输出结果:(多次运行过,除去cpu切换执行其他进程时的特殊情况,结果跟一下结果相差不多)
copy1用时:91毫秒
copy2用时:39毫秒
copy3用时:15毫秒

       直接使用FilerReader的read方法是最慢的,而使用行读取的LineNumberReade是最快的。(另外,如果每个循环中加入flush(),那更是会慢到难以想象。。。所以建议数据多一点再flush())

       我有疑问的是,copy1()和copy2()方法的差距,两个都是一个一个读取,理论上速度应该差不多啊,为什么有缓冲区会快呢?后来我看了Reader的和InputStreamReader源码,发现Reader的read方法每读取一个字符,都会调用一次系统读取数据,而用BufferedReader的read方法,它会默认读取8kb的数据,用数组存放起来,然后每次调用read,返回数组相应角标的数据。所以会明显快的多。

       因此,如果说BufferedReader是对于FileReader的性能增强,是非常明显的,当然还有其他优点1、功能增强。 2、性能提高。3、安全性提高。(线程安全,即使是增加了锁判断的语句,性能依然比直接用Reader中的方法效率高)


评分

参与人数 2技术分 +1 黑马币 +19 收起 理由
╰つ + 19 很高端,很大气
轻语。 + 1 善于思考,且用于实践,赞!

查看全部评分

3 个回复

倒序浏览
谢谢分享。。。。。
回复 使用道具 举报
孟凡超 发表于 2014-5-10 16:24
谢谢分享。。。。。

我修改了刚刚的帖子,原来帖子由于我的疏忽得出了错误的结论,对不住了。
回复 使用道具 举报
牛逼.......
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马