【问题标题】:Garbage Collection behavior垃圾收集行为
【发布时间】:2014-07-11 17:54:30
【问题描述】:

在我的应用程序启动期间,查询数据库,创建对象(根据查询结果)并插入到 Arraylist 中。数组列表稍后被循环并从中创建另一个数据结构。数组列表(大小很大)稍后会被垃圾收集。我的问题是,一次收集这么大的对象是否会对垃圾收集器造成压力。如果我创建一个 QUEUE 数据结构而不是 arraylist。从队列中读取对象将使它们有资格进行 GC。对 GC 的压力是否较小?我知道 GC 可以随时运行,并且不能保证它的执行。除了执行时间之外,我想了解的是,GC 从内存的连续位置(数组列表)收集与 QUEUE 相比是否需要更多的工作,其中内存分配不连续?

【问题讨论】:

    标签: java arraylist garbage-collection queue


    【解决方案1】:

    相对于内存分配不连续的 QUEUE,GC 从连续的内存位置(数组列表)收集是否需要更多的工作?

    清理基于链表的队列比清理 ArrayList 需要更多的工作。这是因为 ArrayList 有两个对象,Queue 每个元素有一个对象。

    如果您想减少 GC 负载,请在读取数据时对其进行处理。这样您就不需要队列或列表,并且您可能会发现在下载数据之前您已经处理了所有数据。也就是说,它也可以更快。

    【讨论】:

      【解决方案2】:

      这里最大的压力来自于在内存中保留“巨大”的对象。如果需要在堆上创建其他对象,则可能会导致 GC 更频繁地工作,甚至在 DB 和 ArrayList 的大小增加时导致“内存不足”异常。

      任何可以让您减少分配给“巨大”对象的内存大小的解决方案都会有所帮助。如果您可以以这样一种方式构建队列,即可以快速释放队列元素而无需等待从数据库中读取所有其他对象,那就去吧。

      正如彼得在他的回答中提到的那样,从数据库中读取对象后立即处理它会更好,而无需对其进行排队或添加到列表中。

      一种可能的解决方案是重新设计您的数据访问层并使用 ResultSet (http://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html),它在我能想到的任何 Java 平台上都可用。由于 ResultSet 保存在 DB 端,您可以一次读取一条记录并显着减少内存压力。

      另一种方法是实现分页,例如通过以这样的方式更改原始查询,即一次只从数据库中读取 ListArray 的一部分。

      【讨论】:

      • 单个查询被触发到返回数据列表的数据库。所以在某种程度上,我必须处理大量数据。
      • 我不知道你是如何访问数据库的,但是有一个叫做“结果集”的东西(见docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html),它是由JDBC支持的。结果集保存在 DB 端,您可以逐条读取记录而不会过多地占用您的内存,因此您可能需要重新设计查询 DB 的方式以避免将来可能出现的中断。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-21
      • 2018-06-10
      • 1970-01-01
      相关资源
      最近更新 更多