我正在以java应用程序的形式运行实用程序类。该类读取包含500万条记录的csv文件,并试图在数据库中保存约125 k记录。中途我发现堆空间错误。完整的文件大约需要5-6小时才能运行。如果将thread.sleep方法作为java应用程序运行,那么添加该方法是否有助于清理资源?我使用spring数据jpa在每1k行之后插入。
String strLine;
List<Provider> providers = new ArrayList<Provider>();
int count = 0;
while ((strLine = br.readLine()) != null) {
String[] providerDetails = strLine.split(",(?=([^\"]*\"[^\"]*\")*[^\"]*$)");
if (providerDetails[31].substring(1, (providerDetails[31].length() - 1)).equals("MD")
|| providerDetails[31].substring(1, (providerDetails[31].length() - 1)).equals("DC")) {
count++;
// add provider to repository
providers.add(convertToProvider(providerDetails));
if (count % 1000 == 0) {
providerRepository.save(providers);
providers.clear();
Thread.sleep(2000);
}
}
}是否还有其他优化可以修复内存问题。我正在使用eclipse,并给它足够的内存。
-Xms128m
-Xmx1536m
-XX:MaxPermSize=768m
-XX:-UseGCOverheadLimit发布于 2014-05-02 15:44:38
我怀疑最大的问题在于使用Hibernate将数据插入数据库的方式。
当您调用EntityManager.persist()或EntityManager.merge()时,您正在处理的实体将被添加到您的EntityManager实例的PersistenceContext中(值得像描述的这里那样在实体生命周期中进行讨论)。
您可以将PersistenceContext看作Hibernate使用的一种缓存,以避免对它已经在当前工作单元中加载的对象进行不必要的访问。此外,Hibernate使用PersistenceContext执行脏检查,以便在提交事务时了解哪些对象需要刷新。
对于少量的对象来说,这很好。当您使用大量对象时,问题就出现了,因为Hibernate出于上述原因保留了对PersistenceContext中每个对象的引用。
因此,重要的是,在执行大批处理插入时,要小心地管理PersistenceContext的大小,要在一定的时间间隔内显式地刷新和清除它,或者对批量插入使用无状态EntityManager。
Hibernate很好地解释了如何在一次这里中处理“很多”实体。我怀疑遵循这个建议会解决你大部分的记忆问题。
发布于 2014-05-02 16:09:02
我将尝试回答您的具体问题,即关于Thread.sleep()对内存问题的影响--我相信其他人会教您如何控制Hibernate的足迹。
我只知道一种情况,即休眠应用程序线程可以帮助避免内存不足,也就是当您大量使用定义了Object.finalize()方法的类的实例时。这些实例经过两轮可达性测试,必须执行single方法;作为垃圾收集的一部分,在单个线程上执行所有实例的single方法。如果您要在多个线程上创建可终结的垃圾,比单个终结器线程所能处理的要快,那么即使您有大量的垃圾可供收集,也会得到一个OutOfMemoryError。通过通过休眠来减缓应用程序线程的速度,您可能会给终结器线程一个追赶的机会。
在这种情况下,这几乎肯定不是您的问题(您有其他明显的原因导致堆空间不足),而睡眠对您没有任何好处。
发布于 2014-05-02 15:27:48
此外,您还必须定期刷新() EntityManager数据库并清除它。
这很可能是你失去记忆的原因。
https://stackoverflow.com/questions/23431535
复制相似问题