2014-07-11 54 views
2

在我的应用程序启动期间,查询数据库,创建对象(从查询结果中)并插入到Arraylist中。数组列表稍后循环,并创建另一个数据结构。 arraylist(这是巨大的)后来被垃圾收集。我的问题是,这是一个垃圾收集器一次收集这样一个大对象的压力。如果我创建一个QUEUE数据结构而不是arraylist,会怎样?从队列中读取对象将使它们符合GC的条件。 GC的应变较小吗?我知道GC可以随时运行,并且不保证它的执行。更多的是执行的时间,我想了解的是,GC从内存的连续位置(ArrayList)收集更多的工作,而不是内存分配不连续的QUEUE?垃圾回收行为

回答

3

对于GC来说,从内存连续位置(arraylist)收集内存分配不连续的QUEUE是否有更多工作要做?

与ArrayList相比,清理基于链表的队列的工作量更大。这是因为ArrayList有两个对象,队列每个元素有一个对象。

如果您想减少GC负载,请在读取数据时处理数据。这样你就不需要一个队列或一个列表,并且你可能会发现你已经在下载的时候处理了所有的数据。即它也可能快很多。

1

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

任何允许您减少分配给“巨大”对象的内存大小的解决方案都会有所帮助。如果可以通过这种方式构建队列,以便队列元素快速释放而无需等待从DB中读取所有其他对象,请执行此操作。

正如彼得在他的回答中所说的,一旦从一个数据库中读取数据而不排入队列或添加到列表中,处理一个对象将会更好。

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

另一种方法是实施分页,例如,通过改变原始查询的方式,使得一次只能从DB中读取一部分ListArray。

+0

将单个查询触发到返回数据列表的DB。所以在某种程度上,我必须处理大量的数据。 –

+0

我不知道你如何访问数据库,但有“结果集”之类的东西(请参阅http://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html ),这是JDBC支持的。结果集保存在数据库端,您可以逐一读取记录,而不会让记忆变得过于紧张,因此您可能需要重新设计查询数据库的方式,以避免将来发生可能的中断。 –