本帖最后由 神马 于 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中的方法效率高)
|