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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

在这里我们将通过几个有趣的例子,来演示Java对象序列化缓存问题。下面这个程序非常神奇,用了不到4秒的时间就向我的硬盘上输出了1000TB的数据。不要怀疑你看错了,确实是不到4秒时间就输出1000TB的数据,不相信你也可以在你的电脑上运行一下这个程序。如果你的硬盘不够大也不用担心,Java完全可以自己解决硬盘容量问题。这个例子对你的电脑唯一的要求就是必须有256M以上的内存,并且要设置执行参数为-Xmx256m。相信现在没有谁的电脑内存是不够256M的。
  1.import java.io.*;
  2.
  3.public class SuperFastWriter {
  4. private static final long TERA_BYTE = 1024L * 1024 * 1024 * 1024;
  5. public static void main(String[] args) throws IOException {
  6. long bytesWritten = 0;
  7. byte[] data = new byte[100 * 1024 * 1024];
  8. ObjectOutputStream out = new ObjectOutputStream(
  9. new BufferedOutputStream(
  10. new FileOutputStream("bigdata.bin")
  11. )
  12. );
  13. long time = System.currentTimeMillis();
  14. for (int i = 0; i < 10 * 1024 * 1024; i++) {
  15. out.writeObject(data);
  16. bytesWritten += data.length;
  17. }
  18. out.writeObject(null);
  19. out.close();
  20. time = System.currentTimeMillis() - time;
  21. System.out.printf("Wrote %d TB%n", bytesWritten / TERA_BYTE);
  22. System.out.println("time = " + time);
  23. }
  24.}
  编译之后,我们就可以执行这个程序了。
  java -Xmx256m SuperFastWriter
  可以看到类似以下的输出
  Wrote 1000 TB
  time = 3710
  你一定会非常奇怪,我用的到底是什么电脑。不仅输出的速度那么快,并且输出的内容完全超出了硬盘容量。每秒钟250 TB,简直是不可思议的事情。
  如果到硬盘上看一下输出的文件,会发现文件只有大概150M。这是因为当我们通过ObjectOutputStream输出一个对象的时候,ObjectOutputStream会将该对象保存到一个哈希表中,以后在输出相同的对象,都会只输出指针,不输出内容。同样的事情也发生在读取对象的时候。Java通过该机制达到最小化数据输入和输出的目的。下面的例子就演示了读取的过程。
  25.import java.io.*;
  26.
  27.public class SuperFastReader {
  28. private static final long TERA_BYTE = 1024L * 1024 * 1024 * 1024;
  29. public static void main(String[] args) throws Exception {
  30. long bytesRead = 0;
  31. ObjectInputStream in = new ObjectInputStream(
  32. new BufferedInputStream(
  33. new FileInputStream("bigdata.bin")
  34. )
  35. );
  36. long time = System.currentTimeMillis();
  37. byte[] data;
  38. while ((data = (byte[]) in.readObject()) != null) {
  39. bytesRead += data.length;
  40. }
  41. in.close();
  42. time = System.currentTimeMillis() - time;
  43. System.out.printf("Read %d TB%n", bytesRead / TERA_BYTE);
  44. System.out.println("time = " + time);
  45. }
  46.}
  在这个例子中,我们去读取刚才输出的文件。虽然文件只有150M左右,但是实际读取的时候,数据量应该是和写出的一样。程序执行时间只需要几秒时间。类似执行结果是:
  Read 1000 TB
  time = 2033
  前面的例子我们反复的将同一个数组写出到文件中,但是并没有修改数组的内容。下面的例子我们将每次写出内容不同的数组。因为Arrays.fill()的执行效率比较低。所以我们只写出256个大数组。
  47.import java.io.*;
  48.import java.util.Arrays;
  49.
  50.public class ModifiedObjectWriter {
  51. public static void main(String[] args) throws IOException {
  52. byte[] data = new byte[10 * 1024 * 1024];
  53. ObjectOutputStream out = new ObjectOutputStream(
  54. new BufferedOutputStream(
  55. new FileOutputStream("smalldata.bin")
  56. )
  57. );
  58. for (int i = -128; i < 128; i++) {
  59. Arrays.fill(data, (byte) i);

1 个回复

倒序浏览
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马