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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 赵晓海 中级黑马   /  2013-12-20 22:26  /  1336 人查看  /  1 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

声明:我只是为了吸引眼球才把标题写的夸张一点,其实极限我也没测出来{:soso_e113:}

下面进入正题
今天看Buffer缓冲区技术视频,老师在讲解缓冲区技术时举的例子很形象。


在写完复制MP3的代码后,运行正常,最短耗时25毫秒左右。然后将缓冲区设置成2048,耗时没有差别。

之后不知道该怎么做才能提高速度,就去百度了一下。看到一个不使用缓冲区技术的代码,处于好奇就拿来作比较。代码如下:

其中:copy_1是缓冲技术,copy_2不是缓冲技术。
  1. import java.io.*;
  2. class Mp3CopyDemo
  3. {
  4.         public static void mp3Copy_1() throws IOException
  5.         {
  6.                 //源:InputStream Reader
  7.                 //不是纯文本:选用字节流 InputStream
  8.                 //需要高效:BufferedInputStream
  9.                 BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("D:\\1.mp3"));
  10.                 //目标:OutputStream Writer
  11.                 //不是纯文本:选用OutputStream
  12.                 //需要高效:BufferedOutputStream
  13.                 BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("D:\\2.mp3"));
  14.                 int bufsz = 1024;
  15.                 byte[] buf = new byte[bufsz];
  16.                 int len = 0;
  17.                 while((len = bufis.read(buf))!=-1)
  18.                 {
  19.                         bufos.write(buf,0,len);
  20.                 }
  21.                 bufis.close();
  22.                 bufos.close();

  23.         }
  24.        
  25.         public static void mp3Copy_2() throws IOException
  26.         {
  27.                 InputStream is = new FileInputStream("D:\\1.mp3");
  28.                 OutputStream os = new FileOutputStream("D:\\3.mp3");
  29.                 int bufsz = 1024;
  30.                 byte[] buf = new byte[bufsz];
  31.                 int len = 0;

  32.                 while((len = is.read(buf))!=-1)
  33.                 {
  34.                                 os.write(buf,0,len);
  35.                 }
  36.                 is.close();
  37.                 os.close();
  38.         }
  39.         public static void main(String[] args) throws IOException
  40.         {
  41.                 long start = System.currentTimeMillis();
  42.                 mp3Copy_1();
  43.                 long end = System.currentTimeMillis()-start;
  44.                 System.out.println(end+"毫秒");
  45.                 start = System.currentTimeMillis();
  46.                 mp3Copy_2();
  47.                 end = System.currentTimeMillis()-start;
  48.                 System.out.println(end+"毫秒");

  49.         }
  50. }
复制代码
运行结果:
25毫秒
90毫秒
多次运行结果与上述结果差别不大。

然后出现一个疑:
虽然第二个没有使用缓冲技术,但是我也用了一个byte[ ]数组做了个临时缓冲区,为什么运行速度却比不上第一个呢?

通过比较代码,两种方法速度差距不在于读取数据的速度差距上,而是在于写入数据的速度差距上。

事实上,查看源代码可以知道BufferedInputStream中的read(byte[ ] buf)方法在其源代码中并不存在,而是直接继承自
FileInputStream的read(byte[ ] buf)方法。所以两种方法中的read方法并没有区别。


分析速度差距原因:
1、查看源代码可知,第一种方法使用缓冲区技术后只有当缓冲区中的数据达到8192个字节后,BufferOutputStream才会将数据写入硬盘
2、第二种方法虽然有缓冲区,但是大小为1024,缓冲区相差8倍。(至于为什么速度相差4倍左右,没想明白)


验证:
如果把两种方法的缓冲区都设为8192,则运行速度相差无几。
大概19毫秒左右。


然后我将第二种方法扩大8192的整数倍,速度下降的不是特别明显,扩大到4倍的时候大概11毫秒左右。

总结:
其实纯粹追求速度没有什么太大的实际意义,真正意义上的读写速度取决于机器的性能。
但是通过这些思考,能比较深入的了解了缓冲区技术。虽然花了两个多小时的时间,但是值得的{:soso_e113:}


文章中的数据是本人电脑实际测试结果,放到其他机器上可能有差距。文章中有不严谨的地方还请大神指正。


测试MP3由于大于2M无法上传,压缩后也不行,如果想要测试可以到我的百度网盘下载,链接如下:
http://pan.baidu.com/s/1gdgKsMZ

评分

参与人数 1技术分 +2 收起 理由
FFF + 2 赞一个!希望以后可以多发这种帖子!.

查看全部评分

1 个回复

倒序浏览
其实,我理解吧,主要还是内存读取和硬盘写入的问题

就像小时候玩的绕圈赛跑,有缓存的就好像数据在内存中绕啊绕啊绕啊--->然后冲刺到终点(硬盘针头转一圈就写完数据了)

而没有缓存的就好像在 赛道上均匀分布转圈的地点,你试试看绝对跑的没上边的快(内存和硬盘操太频繁的缘故)
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马