首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Thread.sleep是否减少读取和保存大文件时的内存问题?

Thread.sleep是否减少读取和保存大文件时的内存问题?
EN

Stack Overflow用户
提问于 2014-05-02 15:19:05
回答 3查看 1K关注 0票数 0

我正在以java应用程序的形式运行实用程序类。该类读取包含500万条记录的csv文件,并试图在数据库中保存约125 k记录。中途我发现堆空间错误。完整的文件大约需要5-6小时才能运行。如果将thread.sleep方法作为java应用程序运行,那么添加该方法是否有助于清理资源?我使用spring数据jpa在每1k行之后插入。

代码语言:javascript
复制
    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,并给它足够的内存。

代码语言:javascript
复制
-Xms128m
-Xmx1536m
-XX:MaxPermSize=768m
-XX:-UseGCOverheadLimit
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-05-02 15:44:38

我怀疑最大的问题在于使用Hibernate将数据插入数据库的方式。

当您调用EntityManager.persist()EntityManager.merge()时,您正在处理的实体将被添加到您的EntityManager实例的PersistenceContext中(值得像描述的这里那样在实体生命周期中进行讨论)。

您可以将PersistenceContext看作Hibernate使用的一种缓存,以避免对它已经在当前工作单元中加载的对象进行不必要的访问。此外,Hibernate使用PersistenceContext执行脏检查,以便在提交事务时了解哪些对象需要刷新。

对于少量的对象来说,这很好。当您使用大量对象时,问题就出现了,因为Hibernate出于上述原因保留了对PersistenceContext中每个对象的引用。

因此,重要的是,在执行大批处理插入时,要小心地管理PersistenceContext的大小,要在一定的时间间隔内显式地刷新和清除它,或者对批量插入使用无状态EntityManager

Hibernate很好地解释了如何在一次这里中处理“很多”实体。我怀疑遵循这个建议会解决你大部分的记忆问题。

票数 3
EN

Stack Overflow用户

发布于 2014-05-02 16:09:02

我将尝试回答您的具体问题,即关于Thread.sleep()对内存问题的影响--我相信其他人会教您如何控制Hibernate的足迹。

我只知道一种情况,即休眠应用程序线程可以帮助避免内存不足,也就是当您大量使用定义了Object.finalize()方法的类的实例时。这些实例经过两轮可达性测试,必须执行single方法;作为垃圾收集的一部分,在单个线程上执行所有实例的single方法。如果您要在多个线程上创建可终结的垃圾,比单个终结器线程所能处理的要快,那么即使您有大量的垃圾可供收集,也会得到一个OutOfMemoryError。通过通过休眠来减缓应用程序线程的速度,您可能会给终结器线程一个追赶的机会。

在这种情况下,这几乎肯定不是您的问题(您有其他明显的原因导致堆空间不足),而睡眠对您没有任何好处。

票数 2
EN

Stack Overflow用户

发布于 2014-05-02 15:27:48

此外,您还必须定期刷新() EntityManager数据库并清除它。

这很可能是你失去记忆的原因。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23431535

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档