本帖最后由 神马 于 2014-5-10 16:49 编辑  
 
对不住大家了,之前由于我的一个疏忽,导致我得出了错误的结论,自我批评中。。。 因为我的copy1、copy2、cpoy3的名字跟时间连在一起了,看起来就是一百多两百多三百多毫秒了,其实是几十毫秒。下面是我修改过后的帖子。  
 关于流缓冲区的效率探索,是从看毕向东老师的JAVA基础视频,产生的疑问开始的。毕老师视频里编写的字节流缓冲器MyBufferedInputStream复制一个Mp3是三百多毫秒,用JAVA库中的BufferedInputStream复制同样的Mp3是五百多毫秒。原理应该是一样的,为什么毕老师的要快,那JAVA库里的BufferedInputStream为什么不优化一下?经过网友的提示,我查看了BufferedInputStream.java的源代码,发现其中大多数的语句都是加了synchronized关键词修饰的,之前学过,同步判断是很影响效率的,尤其是示例程序中,每读取一个字节都要进行一次锁判断,所以导致了BufferedInputStream类的读取速度较慢,而毕老师的MyBufferedInputStream没有任何的同步判断,所以效率要高,速度明显快的多。如果文件更大一些,差距应该更大。 另外,我想研究一下有缓冲区到底比不用缓冲区快多少。于是我自己编了个小程序做试验,程序中的copyfile.txt是个两百多kb的文件。  
- import java.io.*;
 
 - class CopySpeedTest
 
 - {
 
 -         public static void main(String[] args)throws IOException 
 
 -         {
 
 -                 long start=System.currentTimeMillis();        
 
 -                 copy1();
 
 -                 long end=System.currentTimeMillis();
 
 -                 System.out.println("copy1用时:"+(end-start)+"毫秒");
 
 -                 start=System.currentTimeMillis();        
 
 -                 copy2();
 
 -                 end=System.currentTimeMillis();
 
 -                 System.out.println("copy2用时:"+(end-start)+"毫秒");
 
 -                 start=System.currentTimeMillis();        
 
 -                 copy3();
 
 -                 end=System.currentTimeMillis();
 
 -                 System.out.println("copy3用时:"+(end-start)+"毫秒");        
 
 -         }
 
 -         //使用FileReader的read方法一个字符一个字符读取
 
 -         public static void copy1()throws IOException
 
 -         {
 
 -                 FileReader fr=new FileReader("copyfile.txt");
 
 -                 FileWriter fw=new FileWriter("copyfile_copy.txt");
 
 -                 int i;
 
 -                 while((i=fr.read())!=-1)
 
 -                 {
 
 -                         fw.write(i);
 
 -                         //fw.flush();
 
 -                 }
 
 -                 fr.close();
 
 -                 fw.close();
 
 -         }
 
 -         //使用BufferedReader的read方法,一个字符一个字符读取
 
 -         public static void copy2()throws IOException
 
 -         {
 
 -                 FileReader fr=new FileReader("copyfile.txt");
 
 -                 BufferedReader br=new BufferedReader(fr);
 
 -                 FileWriter fw=new FileWriter("copyfile_copy.txt");
 
 -                 BufferedWriter bw=new BufferedWriter(fw);
 
 -                 int i;
 
 -                 while((i=br.read())!=-1)
 
 -                 {
 
 -                         bw.write(i);
 
 -                         //bw.flush();
 
 -                 }
 
 -                 fr.close();
 
 -                 bw.close();
 
 -         }
 
 -         //使用LineNumberReader的行读取方法
 
 -         public static void copy3()throws IOException
 
 -         {
 
 -                 FileReader fr=new FileReader("copyfile.txt");
 
 -                 LineNumberReader lnr=new LineNumberReader(fr);
 
 -                 FileWriter fw=new FileWriter("copyfile_copy.txt");
 
 -                 BufferedWriter bw=new BufferedWriter(fw);
 
 -                 String line=null;
 
 -                 while((line=lnr.readLine())!=null)
 
 -                 {
 
 -                         bw.write(line);
 
 -                         //bw.flush();
 
 -                 }
 
 -                 fr.close();
 
 -                 bw.close();
 
 -         }
 
 - }
 
 
  复制代码       输出结果:(多次运行过,除去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中的方法效率高)  
 |